Fallstudie

Werbung
Verteilte WebApplikationen in
dynamischen
Netzen auf
Basis von Jini
Fallstudie und Evaluierung
Jahresprojekt des Studienganges Computer Networking
Fachhochschule Furtwangen
Sommersemester 1999 und Wintersemester 1999/2000
Prokektteam:
Thomas Mainka, Mirko Tochtermann, Oliver Hilß,
Christian Bister, Maik Dobbermann, Stefan Zier
Verteilte Web-Applikationen in dynamischen Netzen auf Basis von Jini
Fallstudie und Evaluierung
I.)
II.)
III.)
IV.)
V.)
VI.)
VII.)
VIII.)
IX.)
Einleitung
1.) Technologische Grundlagen
a.) Java
b.) RMI
c.) Sicherheit
d.) Servlets
e.) Jini
f.) Vergleich zu CORBA
2.) Überblick über das Projekt
Anwendungsarchitektur
1.) Dienstemarkt
2.) Webserver
3.) Jini als Middleware
4.) Datenbank
5.) Objektmodell der Geschäftsobjekte
6.) Objektmodell des Webservers
Dienste
1.) Der Spielmanager-Dienst
2.) Der Fileserver-Dienst
3.) Der Message-Board-Dienst
4.) Der Mail-Dienst
5.) Der Chatserver-Dienst
a.) Der ChatServer und seine Klassen
b.) Der ChatController
c.) Das ChatOutServlet
d.) Das ChatIn-Servlet
e.) Das Session-Manager-Servlet
Webserver
1.) Service-Controller
2.) Dynamische Seitengenerierung
Datenbank
Praxiserfahrungen, Produkte
1.) Servlet Engines
a.) JRun von Allaire
b.) Tomcat/Jakarta Projekt der Apache Software Foundation
c.) Jserv/Apache Software Foundation
d.) Jigsaw/W3C
2.) Virtual Machines
3.) Jini
a.) Zuverlässigkeit
b.) Managebarkeit
4.) Datenbanken
Performance, Benchmarks
Zusammenfassung, Abschlußbericht
Anhang
1.) Übersicht
2.) Packages
I. Einleitung
I.) Einleitung
Im Rahmen des Studienganges Computer Networking an der Fachhochschule Furtwangen
müssen Studenten ein Jahresprojekt machen. Dazu erhalten Sie entweder hochschulintern
oder aus der Wirtschaft einen Autrag, der innerhalb des vierten und fünften Semesters
umgesetzt werden muß.
Im Sommersemester 1999 wurde durch Herrn Müller-Markmann ein Jahresprojekt initiiert,
das das Ergebnis eines vorangegangenen Jahresprojektes namens net5 evaluieren und
weiterentwickeln sollte. Bei net5 handelt es sich um eine Webplattform zur Durchführung von
Wirtschaftsplanspielen. Das System bot bereits Nachrichtenbretter (Bulletin Boards) und
Dateiaustausch.
Der Dateiaustausch dient hauptsächlich zum Übertragen der Spielzüge. Eine direkte
Webanbindung des Spieles kam leider nicht in Frage, weil die Programmierung einer
Wirtschaftssimulation zu komplex ist. Die verwendete Simulation besteht aus einem
Windows-Client zur Einfabe der Daten und einer DOS-Software zur Durchführung der
Simulation. Der Datenaustausch zwischen diesen beiden Programmen erfolgt über Dateien,
deren Format sich von Version zu Version ändert und deshalb nicht offenliegt.
Zusätzlich zu dem bestehenden System sollte ein mehrsprachiges Benutzerinterface, eine
FAQ (Frequently Asked Questions) sowie ein Chatsystem entwickelt werden, das es den
Spielteilnehmern ermöglicht, in Echtzeit über Spielentscheidungen zu diskutieren.
Zeitgleich kamen Mitarbeiter der Firma SAP auf unsere ehemalige Fachbereichsleiterin Frau
Frank zu und fragten, ob nicht im Rahmen eines der damals beginnenden Jahresprojekte
Jini von Sun etwas genauer erforscht werden könnte. Unser Projekt wurde ausgesucht, da
die Technologie am besten in unser Projekt passte.
Zunächst war eine komplette Neuimplementierung der Planspieleplattform geplant. Nach
einiger Zeit verwarfen wir diese Idee jedoch aus Zeitgründen und entschieden uns, die
bestehende Plattform weiterzuverwenden und parallel dazu eine Fallstudie mit Jini und Java
Spaces zu machen. Im folgenden finden Sie das Ergebnis dieser Fallstudie.
1.) Technologische Grundlagen
a.) Java
Heutzutage werden die meisten verteilten Applikationen, die neu erstellt werden in Java
entwickelt, weil Java-Software nur ein mal compiliert werden muß und auf allen Plattformen
läuft, auf denen eine Java Virtual Machine (JVM) verfügbar ist.
Zudem bietet Java als Sprache Anbindung an fast alle aktuell verfügbaren Technologien,
zum Beispiel Datenbanken (JDBC – Java DataBase Connectivity), Verzeichnisdienste,
Naming-Dienste (JNDI – Java Naming and Directory Interface), Webserver (Servlets, JSP –
Java Server Pages), OMG CORBA (Object Management Group Common Object Request
Broker Architecture).
Weiterhin war Java von vornherein als Sprache für Netzwerke konzipiert, mit RMI ist daher
die Entwicklung von verteilten Applikationen im Vergleich zu den meisten anderen
Entwicklungsumgebungen sehr einfach. Der im Vergleich zu C++ vereinfachte
Sprachumfang und die Garbage Collection ermöglichen somit die schnelle Entwicklung
stabiler Serversoftware.
b.) RMI
RMI (Remote Method Invocation) ist eine parallele zu dem auf Unix-Systemen weit
verbreiteten RPC (Remote Procedure Call). Im Gegensatz zu RPC ist RMI jedoch
objektorientiert und für Client und Server weitgehend transparent – Clients können Methoden
eines Objektes, das auf dem Server „lebt“ (Remote Objekt), in gleicher Weise wie Methoden
lokaler Objekte aufrufen. Der Server „merkt“ nicht, daß der aufrufende Prozeß auf einem
anderen Host läuft.
RMI funktioniert sowohl sehr effizient im LAN (direkt über TCP Sockets) als auch sehr
kompatibel im WAN (getunnelt über HTTP) – sogar durch Firewalls. Dazu muß bei der
Programmierung der Client-Software noch nicht einmal beachtet werden, welches dieser
beiden Verfahren genutzt werden soll. Schlägt die direkte Kommunikation über Sockets fehl,
so findet automatisch ein Fallback auf den HTTP-Tunnel statt. Zudem ist RMI neuerdings
auch interoperabel mit allen CORBA IIOP (Internet Inter-ORB Protocol) kompatiblen
Systemen (RMI over IIOP).
Ähnlich wie bei RPC benutzt auch RMI sogenannte Stubs und Skeletons. Der Stub ist dabei
ein dem Interface des Remote Objektes nachempfundener Wrapper um die
Kommunikationsfunktionalitäten des RMI Clients.
Das Skeleton ist das serverseitige Pendant zum Stub. Er bekommt Requests vom Client, ruft
die Methoden des Remote Objektes auf und liefert die Ergebnisse zurück. Seit JDK (Java
Development Kit) Version 1.2.0 existiert an Stelle der klassenspezifischen Skeletons ein
generisches Skeleton, daher entfällt die Erstellung der Skeletons. Stubs müssen jedoch nach
wie vor mittels eines RMI compilers generiert werden.
c.) Sicherheit
Java-Programme laufen in einer Java Virtual Machine (JVM) ab. Beim Start der JVM wird ein
Sicherheits-Profil geladen, mit dem der JVM mitgeteilt wird, welche Benutzer oder Hosts
welche Befugnisse (Permissions) auf dem Rechner haben.
Permissions sind Java-Klassen. Möchte man den Zugriff auf eine Methode kontrollieren, so
muß man vor deren Abarbeitung abfragen, ob der Aufrufende die entsprechende Befugnis
besitzt.
Dieses System läßt eine sehr feine Dosierung der Zugriffe auf ein System zu.
d.) Servlets
Java Servlets sind der gebräuchlichste Weg, Java-basierte Software über eine
Webschnittstelle verfügbar zu machen. Eine sogenannte Servlet Engine nimmt entweder
direkt oder von einem Webserver Anfragen entgegen und wandelt sie in Response Objekte
um. Zur Generierung der Antwort ruft die Servlet Engine daraufhin eine Methode des
Servlets auf, die anhand des Request Objektes das HTML-Dokument generiert, und es über
das sogenannte Response Objekt an die Servlet Engine zurückgibt.
Im Vergleich zu CGI haben Servlets erhebliche Performance-Vorteile. Außerdem wird ein
Servlet im Gegensatz zu CGI-Skripten nur ein mal gestartet und kann daher Ressourcen
über mehrere Anfragen hinweg benutzen.
e.) Jini
Jini ist eine recht neue, auf Java basierende Technologie, die es ermöglichen soll,
dynamische Netze mit Plug and Play-Funktionalität aufzubauen. Das Hauptaugenmerk liegt
dabei auf dem LAN-Bereich, jedoch ist auch eine Kommunikation im WAN möglich.
Jini-Netzwerke sind Dienst-basiert. Clients können beliebige Dienste ortstransparent nutzen.
Der große Vorteil von Jini ist dabei, daß zum Auffinden eines Dienstes weder dessen Name,
noch der Host auf dem er läuft bekannt sein muß. Stattdessen werden in Jini-Netzen Dienste
mittels Suchprädikaten, die die Eigenschaften des gesuchten Dienstes beschreiben,
gefunden.
Zu diesem Zweck existiert in jedem Jini-Netzwerk mindestens ein sogenannter Lookup
Service. Wird ein Dienst auf einem Host gestartet, so kann er erst dann genutzt werden,
wenn er sich bei mindestens einem Lookup Service registriert hat.
Die Nutzung der Dienste in Jini erfolgt über RMI. Zusätzlich benutzt Jini einen
Kommunikationsmechanismus auf Netzebene, der es erlaubt, den Lookup Service im LAN
mit Hilfe von IP Multicasts aufzufinden (Discovery).
f.) Vergleich zu CORBA
Vergleich man Jini mit CORBA, so kann man feststellen, daß Jini und CORBA sehr ähnliche
Technologien sind, jedoch auf den ersten Blick auf andere Nutzergruppen ausgelegt. Jini ist
eher für den Einsatz mit Clients gedacht – entweder im Customer- und Embedded Bereich
(z.B. zur problemlosen Anbindung von Kleingeräten an Netzwerke), oder aber im Office
Bereich zur Minimierung des Administrationsaufwandes.
CORBA
im
Gegensatz
bietet
Interoperabilität
zwischen
Plattformen
und
Programmiersprachen und nimmt deshalb erheblich komplexere Programmierung und
Administration in Kauf. Aus diesen Gründen wird es hauptsächlich zur Entwicklung verteilter
Enterprise-Applikationen eingesetzt.
2.) Überblick über das Projekt
Bei dem Projekt handelt es sich um eine Webanwendung. Die eigentliche Anwendung nutzt
einige Dienste, die wir als Jini Services implementiert haben. Zu den Diensten zählen:
-
Dateiablage-Service
Nachrichtenbrett-Verwaltung
Spiel- und Spielerverwaltung
Chat-Service
Email-Versand-Service
Einige der Dienste benutzen - für den Benutzer der Dienste transparent - noch persistente
Speicher (Dateisystem bzw. Relationales Datenbanksystem). Die Anwendung selbst konnte
aus Zeitgründen nicht vollständig zu Ende entwickelt werden, jedoch konnten wir
ausreichend Erfahrungen mit Jini und Java Spaces sammeln um diese Fallstudie zu
entwickeln.
Zudem war es möglich, durch einige Benchmarks eine Ahnung von der vorraussichtlichen
Performance des Systems zu bekommen.
II. Anwendungsarchitektur
II.) Anwendungsarchitektur
1.) Dienstemarkt
Um eine hohe Wiederverwendbarkeit der Einzelkomponenten zu erreichen, versucht man in
modernen Software-Anwendungsarchitekturen eine starke Untergliederung in Subsysteme
mit möglichst wenigen Abhängigkeiten untereinander zu erreichen.
Ein solcher Dienstemarkt, wie er in Jini und den meisten anderen
Kommunikationsinfrastrukturen verwendet wird, erfüllt genau diesen Zweck. Komponenten
einer Anwendung werden auf Dienste abgebildet. Abhängigkeiten bestehen nur insofern, als
daß ein Dienst andere Dienste vorraussetzen kann, um zu funktionieren. Dienste sind nach
Außen hin nur anhand ihrer Schnittstellen bekannt. Änderungen in Diensten haben auf
Clients keinerlei Auswirkungen, die Schnittstelle und Funktionsweise bleibt gleich.
Durch diese strikte Trennung wird es möglich, gleichzeitig sehr stabile Systeme zu erstellen
und ein hohes Maß an Wiederverwendbarkeit der Softwarekomponenten zu erreichen.
Für die genannte Planspielapplikation entwirckelten wir die in Kap.I genannten Dienste.
2.) Webserver
Der Webserver bildet die Schnittstelle zwischen dem Webbrowser des Endbenutzers und
dem Dienstemarkt der dem Benutzer zur Verfügung stellt. Gleichzeitig führt er die Dienste in
einen Applikationskontext zusammen, so daß sie für den Benutzer nicht mehr als einzelne
Einheiten erkennbar sind. Auch der Fluß der Applikation sowie die Darstellung der
Benutzerschnittstelle wird vom Webserver übernommen.
Um Wiederverwendbarkeit und Wartbarkeit zu gewährleisten wurde auch der Webserver in
mehrere Stufen unterteilt.
Hierbei galt es zu beachten, daß HTTP und somit auch Servlets Request-Responseorientiert sind, der Fluß der Applikation jedoch in vielen Kontexten mehrere
zusammenhängende Aktion-Reaktion-Kombinationen erfordert.
Um diese unterschiedlichen Charakteristika zu vereinen verwenden Webserver oftmals
sogenannten Sessions. Einem Benutzer wird beim Beginn der Applikation eine Sitzung
zugeordnet. Daten, die bei einem Request im Sessionkontext eines Benutzers gespeichert
wurden sind beim nächsten Request, den ein Benutzer macht, wieder verfügbar. Oftmals
bezeichnet man einen solchen Webserver auch als stateful.
Zu beachten ist jedoch, daß die Session nur Informationen speichern sollte, die den
Applikationsfluß betreffen. Andere Daten sollten von den transistenten und persistenten
Speicherdiensten außerhalb des Webservers gespeichert werden.
Weiterhin benötigt wird auf dem Webserver eine Softwarekomponente, die Informationen,
die zur Laufzeit der Applikation entstehen, mit statischen Texten (HTML-Code und Text)
zusammenführt. Diese Komponente wird im Weiteren als Template-Engine bezeichnet.
Die Trennung von HTML-Code und Applikation hat mehrere Vorteile: Zum einen können die
Texte und der HTML-Code von Personen gewartet werden, die kein oder nur geringes
Wissen über den inneren Aufbau der eigentlichen Applikation wissen, zum anderen ist es
dadurch möglich, die gleiche Funktionalität mit mehreren unterschiedlichen Interfaces zu
präsentieren – also z.B. auch in unterschiedlichen Sprachen – ohne mehrere Versionen des
Applikationsquelltextes pflegen zu müssen.
Schließlich muß das Auffinden, die Kommunikation und die Fehlerbehandlung für die JiniDienste für die Anwendung möglichst an zentraler Stelle stattfinden. Aus diesem Grunde
haben wir ein zentrales Service-Repository eingeplant, das Verbindungen zu Jini Services
aufrecht erhält und den Servlets zur Verfügung stellt. Dadurch muß nicht bei jedem Request
ein Discovery von Diensten stattfinden.
3.) Jini als Middleware
In unserem Fall wird Jini an Stelle von konventioneller Kommunikations-Middleware wie
CORBA oder OSF/DCE eingesetzt. Jini erlaubt einen erheblich dynamischeren Betrieb eines
Dienstemarktes als die meisten heute eingesetzten Kommunikations-Middlewares.
So muß der Standort des Namensdienstes zum Auffinden von Services bei herkömmlicher
Kommunikations-Middleware meist bekannt sein. Oftmals stellt der Namensdienst deswegen
einen sogenannten Single Point of Failure dar. Bei Jini suchen sich sowohl Clients als auch
Services zur Laufzeit Namensdienste (Lookup Service Discovery).
Services registrieren sich bei Lookup Services, um ihre Dienste für Clients zugänglich zu
machen. Clients nutzen Lookup Services, um anhand von bestimmten Merkmalen Services
zu finden. Dadurch wird es möglich, Load Balancing zwischen Lookup Services zu machen
und dynamisch sowohl Lookup Services als auch andere Dienste zum Netz hinzuzufügen
oder vom Netz zu entfernen.
Diese Eigenschaften machen Jini für Serveranwendungen, die sich oft ändern und bei denen
hohe Verfügbarkeit gefordert ist geradezu optimal. Die meisten heutigen Webanwendungen
entsprechen diesem Profil. Durch Jini können Erweiterungen, Softwareupdates und
Umstrukturierungen sehr einfach realisiert werden, ohne daß dabei Systemausfälle
entstehen.
Durch die Beschränkung von Jini auf Java und die Mächtigkeit von RMI können stabile und
performante Anwendungen mit Jini sehr viel schneller entwickelt werden als mit anderer
Kommunikationsmiddleware.
4.) Datenbank
In den meisten heutigen Serveranwendungen werden Datenbanksysteme zur persistenten
Speicherung von Daten verwendet. Weil relationale Datenbanksysteme einen QuasiStandard darstellen entschieden wir uns für ein solches System. Dadurch sollte sichergestellt
sein, daß die Anwendung später einfach zu warten ist.
Java stellt zum Zugriff auf Datenbanken ein API namens JDBC (Java DataBase
Connectivity) zur Verfügung. Seit der Version 1.1 gehört dieses API zum Lieferumfang des
JDK (Java Development Kit).
Der Webserver selbst „kennt“ die Datenbank jedoch nicht. Er kennt nur die Jini Services, die
die Datenbank als Speicher benutzen. Die Daten, die für die Anwendung gebraucht werden,
sind recht einfach. Das Datenbankschema in Kapitel V erläutert den Aufbau der Datenbank.
In der Anwendung gibt es eine Ausnahme in Hinsicht auf persistente Speicherung. Der
Fileserver-Dienst muß größere Mengen an Daten speichern, die von der Anwendung nicht
direkt interpretiert werden müssen. Daher wird hierfür das Dateisystem des Hosts benutzt,
auf dem der Service läuft. Metadaten über die Dateien werden jedoch in der Datenbank
gespeichert.
5.) Objektmodell der Geschäftobjekte
Die Zusammenhänge der Klassen entsprechen weitgehend den Datenbanktabellen. Diese
sind in Kapitel V detailliert besprochen. Zu beachten ist, daß die Klassen jeweils den
Packages des entsprechenden Jini-Services zugeordnet sind.
Detaillierte Dokumentation zu den einzelnen Klassen kann man der API-Dokumentation und
dem Quellcode im Anhang entnehmen.
6.) Objektmodell des Webservers
Zusätzlich zu den Geschäftsobjekten existieren noch Klassen, aus denen die eigentliche
Applikation zusammengesetzt wird. Da die Jini Services im allgemeinen aus einer Klasse
bestehen und daher trivial sind, wird hier nur das Objektmodell des Webservers kurz
erläutert dargelegt.
Im Webserver existiert eine zentrale Stelle, die für die Kommunikation mit der Jini Services
verantwortlich ist. Der sogenannte Service-Controller stellt das Service Repositoy des
Webservers dar. Er stellt den einzelnen Servlets sehr einfache Methoden zur Verfügung, um
Referenzen der Jini Services zu bekommen. Das Discovery und das Lookup wird vom
Service-Controller übernommen.
Die Servlets steuern große Teile der Webanwendung und generieren mit Hilfe einer
sogenannten Template Engine den HTML-Code, der schließlich als Antwort auf eine Anfrage
an den Browser des Benutzers zurückgegeben wird. Alle Servlets benutzen zusammen
einen Service Controller.
III. Dienste
III.) Dienste
1.) Der Spielmanager-Dienst
Der Spielmanager-Dienst ist für die Verwaltung von Spielen, Spielern und Gruppen
zuständig. Zudem dient er zur Authentifizierung der Spieler.
Der Spielmanager-Dienst operiert im allgemeinen mit vier Business-Objekten:
-
Game, stellt ein Spiel dar
GameMaster, der Leiter eines Spieles
Player, ein Mitspieler
Group, eine Gruppe eines Spieles zu der mehrere Spieler gehören
Zur Authentifizierung übergibt der Client des Spielmanager-Dienstes, in unserem Fall also
der Webserver, den Benutzernamen und das Passwort an den Spielmanager-Dienst. Der
Spielmanager-Dienst überprüft das Passwort und liefert – sofern es gültig war – ein PlayerObjekt an den Client zurück.
public Player authenticatePlayer(String login, String password)
Dabei ist zu bemerken, daß der Spielmanager-Dienst das eigentliche Passwort des
Benutzers nie preisgibt, das heißt die Authentifizierung ist in seinem Verantwortungsbereich
angesiedelt.
Ähnliche Methoden existieren auch für Spielleiter. Zudem bietet der Spielleiter-Dienst
Methoden zum Erzeugen, Löschen und Auflisten von Spielen, Spielleitern, Spielern und
Gruppen.
Für die Attribute in den genannten Objekten, wie zum Beispiel die Sprache eines Spielers,
die sich nach der Erzeugung der Spielerobjektes ändern können, existieren Methoden zur
Änderung.
Außerdem stellt der Spielmanager-Dienst auch Methoden zur Verfügung, die es
ermöglichen, allen Spielern eines Spiels, einer Gruppe oder einzelnen Spielern oder
Spielleitern Emails zuzuschicken. Zur Durchführung dieser Aufgaben benutzt der
Spielmanager-Dienst den Mail-Dienst. Schließlich steht noch eine Methode zur Verfügung,
mit deren Hilfe einem Teilnehmer (Spielleiter oder Spieler) , für den Fall daß
er es vergessen hat, eine Mail mit seinem Passwort zugeschickt wird.
2.) Der Fileserver-Dienst
Der Fileserver-Dienst stellt Methoden zur Verfügung, um Dateien zu Speichern und auf
gespeicherte Dateien zuzugreifen. Dateien werden dabei immer in sogenannten Places
gespeichert. Ein Place wird physikalisch auf ein Verzeichnis abgebildet und durch einen
String identifiziert. Der Einfachheit halber verzichteten wir auf eine Verwaltung von
Unterverzeichnissen. Somit ergibt sich eine flache Dateistruktur.
Das einzige Business Object, das der Fileserver-Dienst verwendet ist FileInfo. FileInfo
speichert Zusatzinformationen, die nicht direkt im Dateisystem gespeichert werden können.
Dazu gehört zum Beispiel der Login des Teilnehmers, der die Datei abgespeichert hat.
Die eigentliche Datenübertragung erfolgt über ein byte-Array, das serialisiert und über RMI
verschickt wird.
public byte[] getFile(String place, String name)
public void putFile(String place, String uploader, String name, byte[] content)
Diese Übertragungsart setzt vorraus, daß die gesamte Datei vor der Übertragung in den
Hauptspeicher des Servers geladen werden muß. Dies ist für Anwendungen, bei denen sehr
große oder sehr viele Dateien übertragen werden müssen, nicht praktikabel. Für solche
Anwendungen kann man zum Beispiel Streams verwenden.
Der Einfachheit halber und weil für ein Planspiel keine sehr großen Dateien benötigt werden
haben wir uns dennoch für diese Übertragungsart entschieden.
3.) Der Message-Board-Dienst
Der Message-Board-Dienst verwaltet die Nachrichtenbretter, über die die Teilnehmer der
Planspiele kommunizieren können. Er benutzt ein Business Object namens Message. Eine
Message stellt eine Nachricht dar, die in einem Message-Board veröffentlicht worden ist.
Message-Boards werden über Strings identifiziert.
Die Nachrichten können Bezüge untereinander haben. So kann eine Nachricht eine die
Antwort auf eine andere Nachricht sein. Der Message-Board-Dienst stellt Methoden zur
Verfügung, um Nachrichten zu erzeugen und zu löschen sowie eine Methode, um ein
komplettes Message-Board zu löschen. Wird eine Nachricht zu einem Message-Board
hinzugefügt ohne daß ein Message-Board mit dem angegebenen Namen existiert, so wie
automatisch ein neues Message-Board erstellt.
4.) Der Mail-Dienst
Der Mail-Dienst stellt der Anwendung und anderen Diensten die Möglichkeit zur Verfügung,
E-Mails zu versenden. Dabei besteht die Möglichkeit, Schablonen für eine Mail zu benutzen,
sogenannte Templates.
Templates werden in eine Datenbanktabelle verwaltet, die mit externen Tools oder von Hand
gepflegt werden muß. Die Tabelle enthält unter anderem den kompletten Text und das
Subject.
Folgendes Template ist zum Beispiel denkbar:
Hallo <snd_name> !
Ich freue mich sehr, daß Sie in der Gruppe <group> mitspielen
werden.
Ich
werde
Ihnen
zum
baldmöglichsten
Termin
eine
Spieldiskette für das <game_type> zukommen lassen.
Furtwangen, <datum>,
<game_master_name>
Die von < und > eingeschlossenen Strings stellen Variablen dar, an deren Stelle der MailDienst Werte einsetzt. Einige Werte wie die Email-Adressen des Senders und Empfängers
sind dabei schon vorgegeben, weitere Werte können dem Mail-Dienst in einer Hashtable
mitgeteilt werden.
Folgender Methodenaufruf wird benutzt, um unter Zuhilfenahme eines Templates eine Mail
zu versenden:
public void sendTemplate(String template, String snd_email, String
snd_name, String rcp_email, String rcp_name, Hashtable strings)
Die Hashtable namens string enthält die Werte für die Variablen.
Zum endgültigen Versand der Emails benutzt der Maildienst die Java Mail API und einen
SMTP-Server.
5.) Chat-Server
Der Chat-Server dient zur Kommunikation der Spieler einer Gruppe untereinander und zum
gruppenübergreifenden Chat der gesamten Spielteilnehmer. Der Chat ist im "öffentlichen
Bereich" nicht zugänglich, d.h. am Chat können nur angemeldete Benutzer teilnehmen.
Das Chat-System ist in 5 Komponenten unterteilt.
-
der eigentliche ChatServer, der als Jini-Dienst auf einem beliebigen Server läuft,
der ChatController der als Servlet auf dem Webserver im Hintergrund läuft und die
Verbindung zum ChatServer Jini-Dienst aufnimmt,
das ChatOut-Servlet das die Ausgabe der Chatzeilen für den entsprechenden
Chatroom übernimmt,
das ChatIn Servlet das die Eingabe der Chatzeilen übernimmt und sie an den
ChatController weiterreicht
und das SessionManagement Servlet ist für das Session Management zuständig und
bietet dem Spieler verschiedenste Möglichkeiten Einstellungen für das ChatSystem
vorzunehmen.
a.) Der ChatServer und seine Klassen
Zu Beginn der Implementierungsphase erstellten wir zuerst ein Remote-Interface (Chat)
welches die notwendigen Methoden deklariert. Der ChatController kommuniziert über dieses
Interface mit dem ChatServer.
Die Klasse ChatServer implementiert das Chat-Interface und erhält dadurch folgende
Funktionalität:
Über entsprechende Methoden kann ein Chatroom angelegt bzw. entfernt werden. Ist der
Chatroom bereits angelegt wird keine Aktion ausgeführt.
Der Client (in unserem Fall der ChatController) hat die Möglichkeit über eine Methode eine
bestimmte Anzahl der zuletzt eingefügten Chatzeilen anzufordern. Das ist vor allem sinnvoll
für Spieler die sich neu bei dem Chatroom anmelden.
Weiterhin bietet das Interface eine Methode, um eine neue Chatzeile in einen bestimmten
Chatroom einzufügen. In dieser Methode werden über eine Distributed Event Notification
auch alle registrierten Clients über die neu eingetroffene Chatzeile informiert bzw.
bekommen die neue Chatzeile übergeben. Wir verwenden für die registrierten Clients eine
eigene Klasse (ChatEventData), in der wir die EventDaten ablegen.
b.) Der ChatController
Der ChatController übernimmt die Rolle des "RemoteEventListeners" und erhält Events, die
vom ChatServer beim Eintreffen neuer Chatzeilen versendet werden. Er ist somit in der
Lage, neue Chatzeilen ("verpackt" im Event-Objekt) zu empfangen und in einem Vector
abzulegen. Von dort aus können die Zeilen wiederum weiterverarbeitet werden. Für jeden
Chatroom wird ein ChatController erzeugt. Zur Kontrolle ordnet der ChatController jedem
angemeldeten Client im entsprechenden Chatroom eine nur einmal vorkommende Zahl zu.
c.) Das ChatOut-Servlet
Das ChatOut-Servlet dient der Anzeige aller Chatzeilen für die Clients. Das Servlet bedient
sich des Vektors, welcher vom ChatController gefüllt wird und holt der Reihe nach die
Chatzeile heraus. Dieser Vorgang läuft in einer Endlos-Schleife ab, damit zum einen die
Zeilen mit möglichst verschwindend geringer Verzögerung beim Client angezeigt werden
können und zum anderen der HTTP-Stream stets "offen" gehalten wird.
d.) Das ChatIn-Servlet
Das ChatIn-Servlet beinhaltet die Eingabezeile für die Chat-Benutzer. Sendet der Benutzer
die Eingabe ab, so wird die Chat-Zeile mit dem entsprechenden Benutzernamen ergänzt und
mit der zuvor ausgewählten Farbe formatiert. Dann wird der erzeugte String an den
ChatServer gesendet. Dabei wird auch der Name des Chatrooms übergeben, damit die Zeile
auch bei den richtigen Chat-Benutzern (die im gleichen Chatroom angemeldet sind) erscheint. In unserem Codebeispiel erzeugen wir standardmässig einen Chatroom „room2“, da
die gesamte Applikation, die auch die Übergabe des zu erstellenden Chatrooms beinhaltet,
noch nicht komplett programmiert wurde.
e.) Das SessionManager-Servlet
Das SessionManager-Servlet erstellt pro angemeldeten Benutzer eine eindeutige Session,
auf die die Servlets zugreifen können. Auf diese Art können die Servlets Client-Bezogene
Daten austauschen. Wir verwenden diese Möglichkeit in unserem Chatsystem um dem
Benutzer die Auswahl aus verschiedenen Farben (schwarz, grün, rot, blau) zu ermöglichen
und seinen „Nickname“ zu setzen.
Wurde noch kein SessionManager-Servlet erzeugt greift das ChatIn-Servlet auf DefaultWerte zurück.
IV. Webserver
IV.) Webserver
1.) Service-Controller
Wie in Kapiel II.2 schon kurz erwähnt implementierten wir ein generisches ServiceRepository, das es dem Webserver ermöglichen soll, eine ständige Verbindung zu JiniDiensten aufrecht zu erhalten.
Dabei sollte ein Failover-Mechanismus implementiert werden, der die Verfügbarkeit von
Diensten in regelmäßigen Intervallen überprüft. Fällt ein Dienst aus, so an dessen Stelle ein
anderer, gleichwertiger Dienst benutzt werden, der im Netzwerk angeboten wird.
Als Schnittstelle zwischen dem eigentlichen Webserver und den Jini-Diensten
implementierten wir deswegen einen Service-Controller. Zusätzlich zu den oben genannten
Funktionen hat der Service-Controller die Aufgabe, für den Fall, daß ein Dienst ausfällt und
für eine gewisse Zeit kein Ersatzdienst auffindbar ist, einen Systemadministrator per Email
zu benachrichtigen.
Beim Start des Webservers muß dieser den Service-Controller instantiieren und diesem
mitteilen, welche Jini-Dienste er benötigt. Dazu stellt der Service-Controller folgende
Methode bereit.
public void addSearchClass(String classname)
Ähnliche Methoden mit anderen Suchkriterien währen natürlich denkbar und sinnvoll, wir
beschränkten und jedoch im Rahmen dieser Fallstudie darauf, den Klassennamen des JiniDienstes als Suchkriterium zu verwenden. Entsprechend gibt es auch eine Methode, um
einen Klassennamen von der Liste der gesuchten Dienste zu entfernen.
Danach kann der Webserver den Service-Controller mittels folgender Methode benutzen:
public Object getService(String classname)
Die Methode liefert direkt eine Referenz auf den gesuchten Dienst zurück. Dieser
Methodenaufruf wird in aller Regel von dem Code benutzt, der eine HTML-Seite generiert.
Um eine hohe Verfügbarkeit des Webservers zu erreichen kann man unter Zuhilfenahme der
oben genannten Failover-Mechanismen mehrere Instanzen der einzelnen Dienste auf
unterschiedlichen Hosts starten. Fällt einer der Hosts aus, so führt der Service-Controller ein
erneutes Discovery durch und verwendet ab diesem Zeitpunkt einen alternativen Dienst.
Zusätzlich wäre denkbar, auf Basis des Dienstemarktes von Jini einen sehr dynamischen
Load-Balancing-Mechanismus zu implementieren. Dazu müsste man den Service-Controller
so modifizieren, daß er alle Verfügbaren Dienste abwechselnd benutzt.
2.) Dynamische Seitengenerierung
Auch die Generierung der HTML-Seiten basiert auf Templates. Wie schon in Kapitel II.2
erwähnt, sollte die eigentliche Programmierung und die Entwicklung der HTML-Seiten von
verschiedenen Personen möglichst getrennt durchzuführen sein.
Zum Einsatz kam dazu eine Template Engine von Stefan Zier namens FastHtml. FastHtml
unterteilt HTML-Seiten in sogenannte Blöcke. Dabei hat jede HTML-Seite einen Hauptblock,
der den Rahmen für die Seite darstellt. Weitere Blöcke, die entweder aus anderen Dateien
geladen werden oder in der Hauptdatei definiert werden können dienen als Hilfsmittel, um
die komplette Seite zu gestalten. Folgendes Beispiel verdeutlicht die Funktionsweise:
<% servlet="mm.fasthtml.FastHtmlTest" %>
<html>
<head>
<title>$$ var="title" $$</title>
</head>
<body bgcolor="$$ body_color $$">
<h2>$$ var="headline" $$</h2>
Hello $$ var="name" $$ how are you?<p>
<table>
$$ var="member_list" $$
</table>
</body>
</html>
<% block="member_list_line" %>
<tr>
<td>$$ var="name" $$</td>
<td><a href="mailto:$$ var="email" $$"><b>$$ var="email"
$$</b></td>
<td>$$ var="phone" $$</td>
</tr>
Die Tags, die mit <% und %> umgeben sind stellen den Beginn einer Blockdefinition dar.
Tags die von $$ umgeben sind sind Variablen innerhalb eines Blockes. Variablen können
entweder direkt vom zugehörigen Servlet eingesetzt werden, oder es können statisch Blöcke
inkludiert werden.
Beim Aufruf einer URL (z.B. http://net5.foo.fh-furtwangen.de/index.fh) wird zunächst die
Template-Engine aufgerufen, die dann die Kontrolle an das in der servlet=-Klausel des
Hauptblocks genannte Servlet abgibt. Nachdem das Servlet die entsprechenden Variablen
einer Hashtable mit Werten gefüllt hat (ggf. unter Zuhilfenahme von Blocks) gibt es die
Kontrolle zurück an die Template-Engine, die sich schließlich um die Ausgabe der Seite zum
Benutzer kümmert.
V. Datenbank
V.) Datenbank
Die folgende Grafik zeigt das zugrundeliegende Datenbankschema.
Mail_template
file
gameMaster
game
PGroup
msgboard
Player
message
Abbildung 5.1 Datenbankschema
Wie man erkennen kann, sieht das Schema mehrere Spielleiter vor. Jedes Spiel hat genau
einen Spielleiter. Ein Spielleiter kann mehrere Spiele verwalten. Ein Spiel hat mehrere
Gruppen, jede Gruppe gehört zu genau einem Spiel. Das gleiche Verhältnis besteht
zwischen einem Spieler und einer Gruppe.
Jede Gruppe hat zudem ein Nachrichtenbrett. Darüberhinaus hat jedes Spiel ein
Nachrichtenbrett, das für alle Spielergruppen erreichbar ist. Ein Nachrichtenbrett hat mehrere
Nachrichten, die jeweils einem Spieler (dem Absender) zugeordnet sind. Zudem hat eine
Nachricht optional eine Elternnachricht, also ist die Antwort auf eine andere Nachricht.
Weiterhin können Gruppen und Spiele beliebig viele Dateien haben. Schließlich gibt es eine
Tabelle, in der die Mail Templates gespeichert werden.
VI. Praxiserfahrungen, Produkte
VI.) Praxiserfahrungen, Produkte
1.) Servlet Engines
Im Laufe unseres Projektes testeten wir vier verschiedene Servlet-Engines. Aufgrund
positiver Erfahrungen eines unserer Projektmitglieder mit JRun von Live-Software
(mittlerweile von Allaire gekauft) entwickelten wir zuerst mit JRun als Servlet-Engine.
a.) JRun von Allaire
JRun erfüllte unsere Bedingungen, es war frei verfügbar (in der Standard-Version), es
unterstützte das Pre-Loading von Servlets und es war bezüglich der Performance für unsere
Anwendung ausreichend.
JRun bietet die Möglichkeit entweder als Modul für Apache zu laufen, oder als
eigenständiger Webserver. Wobei bei letzterer Anwendung alle html-pages als Servlets bzw.
Jsp-Seiten geschrieben sein müssen. Wir entschieden uns für den Einsatz von JRun als
Standalone-Webserver.
Bis zu einem gewissen Punkt hatten wir keine Probleme mit JRun, wenn man von den etwas
unübersichtlichen Konfigurationsdateien und der mageren Dokumentation absieht.
Weitaus grössere Probleme bereitete uns die Ausgabe der Chatzeilen in unserem Servlet.
Die Ausgabe erschien immer erst nach einer gewissen Zeit bzw. einer gewissen Anzahl von
übertragenen Bytes. Wir nahmen an, dass es sich dabei um einen Buffer handelt, der die
Ausgabedaten erst zwischenspeichert und nach einer bestimmten Anzahl von Bytes ausgibt.
Nach mehrmaliger Rücksprache mit Live-Software stellte sich heraus, dass es sich um einen
„hardgecodeten“ internen Buffer von JRun handelt.
Somit war unsere mehrwöchige Arbeit mit dieser Plattform obsolet und wir mussten uns nach
einer anderen Servlet-Engine umsehen.
b.) Tomcat/Jakarta Projekt der Apache Software Foundation
Diese Servlet-Engine bietet ebenfalls die Möglichkeit als Standalone-Webserver zu arbeiten
oder mit Hilfe eines Connectors als Servlet-Engine für den Apache-Webserver zu arbeiten.
Leider war dieses Produkt zum Zeitpunkt unseres Tests noch sehr instabil und auch zu
langsam um unseren Anforderungen zu genügen. Es stellte sich auch heraus, dass diese
Servlet-Engine nicht das Pre-Loading von Servlets unterstützt. Die Installation erwies sich als
äusserst schwierig und schlecht dokumentiert.
Wir kamen nach einer kurzen Testphase zu dem Schluss, dass diese Servlet-Engine nicht
unseren Ansprüchen genügt.
c.) Jserv/Apache Software Foundation
Jserv kann nur als Modul in Verbindung mit dem Apache Webserver eingesetzt werden. Zur
Kommunikation zwischen dem Webserver und Jserv wurde ein eigenes Protokoll entwickelt.
Nach etwas schwieriger Installation stellte sich heraus, das dieses Protokoll eine
Leistungsbremse für die Servlet-Engine darstellt. Ausserdem gab es zu bemängeln, dass die
Dokumentation im Bezug auf Einrichtung eines Servlets zu mager war.
Es stellte sich dann auch als zu kompliziert heraus, ein einfaches Servlet einzubinden und zu
testen. Jserv arbeitet mit sog. Servlet Zones die über 3 verschiedene Konfigurationsfiles
konfiguriert werden müssen.
Jserv bietet die Möglichkeit des Pre-Loadings von Servlets, leider wurden wir in der
Dokumentation nicht fündig, wie man dieses Feature aktiviert.
Zudem hatte Jserv dasselbe Problem wie JRun in bezug auf die Ausgabe unseres
ChatServlets – die Zeilen erschienen stark verzögert nach der Eingabe.
Somit kam auch diese Servlet-Engine für uns nicht mehr in Frage.
d.) Jigsaw/W3C
Jigsaw ist ein Standalone-Webserver mit Servlet-Engine. Angenehm aufgefallen ist uns die
sehr einfache, wie auch reibungslose Installation von Jigsaw. Des Weiteren wird auch eine
sehr ausführliche Dokumentation mitgeliefert. Zudem bietet Jigsaw die Möglichkeit die
Servlets per Java-Administrationstool sehr einfach grafisch einzubinden.
Mit dieser Servlet-Engine war es nun endlich möglich, unser ChatServlet ohne verzögerte
Ausgabe laufen zu lassen. Ein weiterer grosser Vorteil von Jigsaw ist seine ausgezeichnete
Performance und sein sehr gutes Antwortverhalten unter Vollast (siehe dazu Kapitel VII).
Letztendlich bietet Jigsaw die Möglichkeit Servlets dynamisch im laufenden Betrieb
hinzuzufügen und zu testen, was sich gerade in der Testphase als sehr nützliches Feature
erweist.
2.) Virtual Machines
Im Rahmen des Projektes analysierten wir auch einige Java Virtual Machines. Da wir als
Zielplattform entweder Linux oder Solaris einsetzen wollten analysierten wir speziell diese
Plattformen.
Für Solaris gibt es aktuell nur die JVM von Sun, wahlweise mit einer sogenannten
Performance Engine namens HotSpot, ein etwas ausgeklügelterer JIT (Just-In-TimeCompiler). Wir testeten diese JVM in der Version 1.2.2. Die Performance war
erwartungsgemäß sehr gut, mit Hotspot noch etwas besser. Auch waren keine
Stabilitätsprobleme festzustellen.
Für Linux gibt es mittlerweile recht viele JVMs. Wir schauten uns IBMs JVM 1.1.8, die
Betaversion des Blackdown-Ports der Sun JVM sowie den Release Candidate 1 der JVM
von Sun an.
Die IBM JVM schied recht bald aus, da Jini auf Java 1.2 aufsetzt. Ansonsten stellten wir bei
der IBM JVM die beste Performance unter Linux fest. Leider war die JVM nicht immer stabil
und zeigte stellenweise Fehler.
Der Blackdown-Port ist höflich ausgedrückt als Katastrophe zu bezeichnen. Keiner unserer
Tests mit vielen Threads lief durch. Entweder die JVM blieb einfach stehen oder
verabschiedete sich mit einem Segmentation Fault. Bei den anderen Tests „glänzte“
Blackdown durch mangelhafte Performance.
Der erst seit kurzer Zeit verfügbare Release Candidate 1 der Sun JVM 1.2.2 für Linux, der
aus dem Blackdown-Source-Tree heraus in Zusammenarbeit mit Inprise entwickelt wurde
machte hingegen einen sehr guten Eindruck. Die Performance war zwar nicht ganz so gut
wie die der IBM JVM, jedoch lief der Release Candidate 1 schon erheblich stabiler als die
anderen beiden Kandidaten unter Linux.
Weil unsere Zielplattform vermutlich ein Intel-Rechner gewesen wäre und Solaris/Intel eher
eine Exotenrolle spielt, hätten wir uns für Linux mit der Sun JVM entschieden.
3.) Jini
a.) Zuverlässigkeit
Zu Projektbeginn war Jini von Sun Microsystems in der Version 1.0 verfügbar. Mit dieser
Version arbeiteten wir in den ersten beiden Monaten. Hierbei kam es immer wieder zu
Problemen beim Starten des RMI-Daemons und dem Starten des Lookup-Service. Dies
führte teilweise dazu, dass auf dem Entwicklungssystem zehn und mehr Java Virtual
Machines gestartet wurden. Dieses Phänomen hat zur Anfangsphase unseren
Entwicklungsfortschritt stark eingeschränkt. Konnte der Jini-Dienst einmal gestartet werden,
lief es, auch über eine längere Zeit, stabil und zuverlässig.
Seit der Version 1.01 der Jini-Implementation verschwanden diese Probleme vollständig.
Besonders während der Tests unserer Dienste konnten wir dadurch viel Zeit und Arbeit
sparen.
Als Fazit bleibt zu sagen, dass Jini zumindest seit der Version 1.01 durchaus im produktivem
Umfeld einsetzbar ist und auch stabil und zuverlässig läuft. Dabei sind jedoch die
Anmerkungen zur Managebarkeit im nächsten Punkt zu beachten.
b.) Managebarkeit
Damit alle Voraussetzungen für ein funktionstüchtiges Jini-System mit mehreren JiniDiensten in einer heterogenen Umgebung erfüllt werden können, ist gleich zu Beginn mit
einem erheblichen Konfigurationsaufwand zu rechnen. Grundlegende Dienste, wie zum
Beispiel der Lookup-Service zum Anmelden und Auffinden von Diensten, müssen auf jeden
Fall stabil und zuverlässig laufen. Andernfalls muss man während der Entwicklungs- und
Testphase grosse Probleme in Kauf nehmen (z.B. bei der Fehlersuche).
Zu den grundlegenden Konfigurationsarbeiten gehört die Erstellung eines Start-Skripts für
den Jini-Lookup-Service und das Setzen des korrekten "Classpaths“.
Es wäre zu wünschen, dass Sun in Richtung Managebarkeit noch eine einfachere Lösung
bereitstellen würde, da die meisten Administratoren mit dem bisher notwendigen Aufwand
überfordert sind, bzw. ihnen die Zeit fehlt, das System aufzusetzen.
4.) Datenbanken
Aufgrund der sehr einfach strukturierten Datensätze und der Bedingung, dass die von uns
verwendete Datenbank nichts kosten darf, entschieden wir uns für MySQL als
Datenbanksystem.
MySQL von T.c.X DataKonsultAB (www.tcx.se) ist für Privatanwender kostenlos. Zudem ist
die Installation sehr einfach und mit MySQL kommt eine sehr ausführliche Dokumentation
mit. Es handelt sich hierbei um ein multi-threaded und multi-user Datenbanksystem, das auf
verschiedenen Plattformen läuft und bietet APIs für Programmiersprachen wie C, C++, Java,
Perl etc., um einige Features zu nennen.
Obwohl mysql keine referentielle Integrität und prepared Statements bietet war es für unsere
Anwendungszwecke völlig ausreichend.
VII. Performance, Benchmarks
VII.) Performance, Benchmarks
In diesem Kapitel versuchen wir einen Einblick in die Möglichkeiten einer Jini-Anwendung im
Hinblick auf Performance zu geben. Wir testeten unsere Applikation nur mit der ServletEngine vom W3C (Jigsaw). Trotzdem kann man dadurch Rückschlüsse auf die
Leistungsfähigkeit einer Jini/Servlet Applikation erhalten. Im folgenden sei unser Testsystem
kurz umrissen:
Hardware:
- Sun Ultra1 170MHZ
- 192MB RAM
- 2*IBM SCSI HD (2GB+4GB)
- Onboard 10mbit Netzwerkkarte
Software:
- Solaris 7 Kernel patch 106541-07
- Jigsaw 2.03
- JDK 1.2.1_04 ohne HotSpot
- JSDK 2.0
- Jini 1.0.1
- MySQL 3.22.26a
Alle unsere Dienste liefen auf dieser Maschine. Mann kann sícher noch eine
Performancesteigerung erreichen, wenn man diese Dienste auf verschiedene Maschinen
verteilt. Auch die Begrenzung der Netzwerkkarte auf nur 10 MBit kann ein Bottleneck
darstellen.
Als Benchmark kam ein selbstentwickeltes Java-Tool zum Einsatz, das in mehreren Threads
permanent Requests an eine bestimmte URL schickt. Das Benchmark-Tool lief dabei auf
einer separaten Maschine.
Wir führten 3 Tests mit jeweils 3 Durchgängen von jeweils zwei Minuten durch. Es wurden
150 Threads erzeugt, welche die Page-Views erzeugen.
1. Test: Jigsaw in Verbindung mit einer ganz normalen Html-Seite.
2. Test: Jigsaw in Verbindung mit einem Servlet das keinen jini-Dienst in Anspruch nimmt.
3. Test: Jigsaw in Verbindung mit einem Servlet das einen Jini-Dienst in Anspruch nimmt.
Im Folgenden ist für jeden Testlauf (Run) die Anzahl der erreichten Page-Views zusammen
mit dem Durchschnitt angegeben:
Run1
Test1
Test2
Test3
Run2
18287
16576
12087
Run3
18305
16631
12275
Durchschnitt
18461
16404
12141
18351
16537
12168
Test1: Jigsaw in Verbindung mit einer ganz normalen
Html-Seite
18500
Page-Views
18450
18400
18350
18300
18250
Du
rch
sc
hn
itt
Ru
n3
Ru
n2
Ru
n1
18200
Du
rch
sc
hn
itt
Ru
n3
Ru
n2
16650
16600
16550
16500
16450
16400
16350
16300
16250
Ru
n1
Page-Views
Test2: Jigsaw in Verbindung mit einem Servlet das
keinen jini-Dienst in Anspruch nimmt
Test3: Jigsaw in Verbindung mit einem Servlet das
einen Jini-Dienst in Anspruch nimmt
12300
12200
12150
12100
12050
12000
Du
rch
sc
hn
itt
Ru
n3
Ru
n2
11950
Ru
n1
Page-Views
12250
VIII. Zusammenfassung,
Abschlußbericht
VIII.) Zusammenfassung
Die genannten Technolgien eignen sich unseres Erachtens sehr gut zur Entwicklung
ausbaubarer, ausfallsicherer und skalierbarer, verteilter Webapplikationen. Jedoch befinden
sich einige der Technologien noch in einem frühen Stadium. Daher entstehen oftmals
Schwierigkeiten und schwer zu erklärende Fehler.
Durch die Vielzahl der Technologien, die für eine derartige Applikation zusammenarbeiten
müssen, ist der Aufbau einer einfach zu wartenden Laufzeitumgebung mitunter eine sehr
komplexe Aufgabe. Weiterhin ist eine solche Umgebung für einen Systemadministrator, der
nicht aktiv an der Entwicklung der Software beteiligt ist, schwer oder gar nicht
nachzuvollziehen. Deswegen sollte man bei derartigen Projekten speziell auf ein stark
ausgeprägtes Konfigurationsmanagement achten. Ohne diese Grundlage wird es unmöglich,
den Zeitaufwand für die Entwicklung und den Test von Applikationen abzuschätzen.
Weiterhin ist es empfehlenswert, im Laufe des Projektes eine Art Knowledge-Base für
schwer zu findende Probleme einzurichten. Zudem sollte man soweit möglich im Vorfeld des
Projektes Zielplattform und Tools (Virtual Machine, Servlet Engine etc) testen und auswählen
und die Anwendungen in dem so entstehenden Umfeld entwickeln.
IX. Anhang
IX.) Anhang
1.) Übersicht
Im Folgenden ist der Einfachheit halber die komplette API-Dokumentation sowie der
Quellcode der Fallstudie abgedruckt. Der Quellcode sowie die komplette Dokumentation sind
ebenfalls auf der beigelegten CD-ROM zu finden.
WICHTIG: Die Software ist nur soweit implementiert, daß die für die Fallstudie wichtigen
Schlüsse gezogen werden konnten. Sie ist nicht geeignet, um im Produktionsbetrieb
eingesetzt zu werden. Viele Funktionen sind fehlerhaft oder fehlen.
2.) Packages
Im folgenden eine kurze Übersicht über die Packages, aus denen die Software besteht.
Package
mm.jini
mm.services
mm.services.chat
mm.services.files
mm.services.game
mm.services.mailer
mm.services.msgboard
mm.tools
mm.webserver
mm.webserver.servlets
mm.webserver.sessions
Bedeutung
Klassen,
die
im
unmittelbaren
Zusammenhang mit Jini stehen
Die Jini-Dienste
Klassen des Chat-Dienstes
Klassen des File-Dienstes
Klassen des Spielverwaltungs-Dienstes
Klassen des Mail-Dienstes
Klassen des Messageboard-Dienstes
Diverse Hilfsklassen
Klassen,
die
im
unmittelbaren
Zusammenhang mit dem Webserver
stehen
Servlets
Session-Management
a.) mm.jini
Dieses Paket enthält lediglich den Service-Controller. Er wird in diesem Projekt nur vom
Webserver benutzt, anderer Einsatz ist jedoch denkbar.
Klasse
ServiceController
Bedeutung
Verwaltet die Verbindung zu mehreren Jini
Services
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.jini.ServiceController
mm.jini.ServiceController
public class ServiceController
Service Controller. Managed Discovery und Lookup und die Suche nach
bestimmten Services. Erhält einen Thread am Leben, der ggf. ausgefallene
Services automatisch wieder sucht und zur Verfügung stellt.
Version:
1.0
Author:
Stefan Zier
ServiceController()
Konstruktor.
addSearchClass(String)
Fügt eine Klasse zur Suchliste hinzu
checkServices()
Überprüft ob alle Services noch laufen.
discarded(DiscoveryEvent)
Wird aufgerufen wenn Lookup Services verschwinden
discovered(DiscoveryEvent)
Wird aufgerufen wenn ein Lookup Service gefunden wird
findServices()
Versucht Services die nicht mehr laufen wieder zu finden.
getService(String)
Liefert einen gefundenen Service zurück.
removeSearchClass(String)
Löscht eine Klasse aus der Suchliste
searchClasses()
Sucht alle bekannten Lookup Services nach den verlangten Klassen ab
und fügt sie ggf.
ServiceController
public ServiceController() throws java.io.IOException
Konstruktor. Startet das Lookup Discovery.
getService
public java.lang.Object getService(java.lang.String classname)
Liefert einen gefundenen Service zurück.
Parameters:
classname - der Name der Serviceklasse
Returns:
einen Pointer auf die Serviceklasse
addSearchClass
public void addSearchClass(java.lang.String classname)
Fügt eine Klasse zur Suchliste hinzu
Parameters:
classname - der Name der Klasse die gesucht werden soll
removeSearchClass
public void removeSearchClass(java.lang.String classname)
Löscht eine Klasse aus der Suchliste
Parameters:
classname - der Name der Klasse die entfernt werden soll
discovered
public void discovered(net.jini.discovery.DiscoveryEvent event)
Wird aufgerufen wenn ein Lookup Service gefunden wird
Parameters:
event - das Event
discarded
public void discarded(net.jini.discovery.DiscoveryEvent event)
Wird aufgerufen wenn Lookup Services verschwinden
Parameters:
event - das Event
checkServices
public boolean checkServices()
Überprüft ob alle Services noch laufen.
Returns:
true wenn alle Services noch laufen
findServices
public void findServices()
Versucht Services die nicht mehr laufen wieder zu finden.
searchClasses
public void searchClasses()
Sucht alle bekannten Lookup Services nach den verlangten Klassen
ab und fügt sie ggf. zu dem Vector hinzu.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.jini;
// Java core imports
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
// Jini imports
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.core.lookup.ServiceMatches;
import net.jini.core.lookup.ServiceItem;
// Project imports
import mm.tools.AliveCheckable;
/**
* Service Controller. Managed Discovery und Lookup und die Suche nac h
bestimmten Services.
Services
* Erhält einen Thread am Leben, der ggf. ausgefallene Services automatisc h
wieder sucht
* und zur Verfügung stellt.
stellt
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class ServiceController implements DiscoveryListener
{
protected Vector searched = null;
protected Hashtable found = null;
protected Vector registrars = null;
protected Hashtable last_status = null;
private final String STATUS_OK = "OK";
private final String STATUS_NEW = "NEW";
private final String STATUS_ERROR = "ERROR";
private final String MAIL_SERVER = "mm.services.mailer.MailServer";
private final String STATUS_MAIL_RECIPIENT = "[email protected]";
// 2 Minuten, länger darf nicht auf einen Dienst gewartet werden
private final long timeout = 120000;
private long start_time;
/**
* Konstruktor. Startet das Lookup Discovery.
Discovery
*/
public ServiceController()
throws IOException
{
// searched, found und registrars initialisieren
searched = new Vector();
found = new Hashtable();
registrars = new Vector();
last_status = new Hashtable();
// lookup discoverer starten
LookupDiscovery ld = new LookupDiscovery(LookupDiscovery.NO_GROUPS);
// uns selbst als discovery listener hinzufügen
ld.addDiscoveryListener(this);
ld
// lookup discoverer starten
ld.setGroups(LookupDiscovery.ALL_GROUPS);
ld
// searcher thread starten
new SearcherThread().start();
// Starttime festhalten
start_time = System.currentTimeMillis();
}
/**
* Liefert einen gefundenen Service zurück.
zurück
*
* @param classname der Name der Serviceklass e
* @return einen Pointer auf die Serviceklass e
*/
public Object getService(String classname)
{
return found.get(classname);
}
/**
* Fügt eine Klasse zur Suchliste hinz u
*
* @param classname der Name der Klasse die gesucht werden sol l
*/
public void addSearchClass(String classname)
{
searched.addElement(classname);
searched
last_status.put(classname, STATUS_NEW);
last_status
}
/**
* Löscht eine Klasse aus der Suchlist e
*
* @param classname der Name der Klasse die entfernt werden sol l
*/
public void removeSearchClass(String classname)
{
searched.removeElement(classname);
searched
found.remove(classname);
found
last_status.remove(classname);
last_status
}
/**
* Wird aufgerufen wenn ein Lookup Service gefunden wir d
*
* @param event das Event
*/
public void discovered(DiscoveryEvent event)
{
System.out.println("discovered() lookup service(s) discovered");
System
// neue Lookup Services holen
ServiceRegistrar[] regs = event.getRegistrars();
ServiceRegistrar
// nach und nach in den Vector schreiben
for(int i=0; i<regs.length ;i++)
for
registrars.addElement(regs[i]);
registrars
}
/**
* Wird aufgerufen wenn Lookup Services verschwinde n
*
* @param event das Event
Even
*/
public void discarded(DiscoveryEvent event)
{
System.out.println("discarded() lookup service(s) discarded");
System
// verschwundene Lookup Services holen
ServiceRegistrar[] regs = event.getRegistrars();
ServiceRegistrar
// nach und nach aus dem Vector löschen
for(int i=0; i<regs.length ;i++)
for
registrars.removeElement(regs[i]);
registrars
}
/**
* Überprüft ob alle Services noch laufen .
*
* @return true wenn alle Services noch laufe n
*/
public boolean checkServices()
{
System.out.println("checkServices() invoked");
System
// alle Services durchlaufen
Enumeration enum = searched.elements();
while
while(enum.hasMoreElements())
{
String key = (String)enum.nextElement();
AliveCheckable ac = null;
try
{
ac = (AliveCheckable) found.get(key);
}
catch(ClassCastException cce)
catch
{
continue;
continue
}
if
if(ac
== null)
{
reportError(key);
reportError
return false;
}
try
{
if(!ac.isAlive())
if
return false;
}
catch(RemoteException re)
catch
{
return false;
}
}
// wenn einer nicht läuft false zurückliefern
return true;
}
/**
* Versucht Services die nicht mehr laufen wieder zu finden .
*/
public void findServices()
{
System.out.println("findServices() invoked");
System
if
if(registrars.size()
== 0)
{
System.out.println("findServices() no lookup services found yet");
System
return;
return
}
// alle kaputten services aus der Hashtable werfen
Enumeration enum = found.keys();
while
while(enum.hasMoreElements())
{
String key = (String)enum.nextElement();
AliveCheckable ac = null;
try
{
ac = (AliveCheckable) found.get(key);
}
catch(ClassCastException cce)
catch
{
System.out.println("findServices() " +
System
found.get(key).getClass().getName() + " does not implement
AliveCheckable");
continue;
continue
}
try
{
System.out.println("findServices() checking if " +
System
ac.getClass().getName() + " is still alive...");
if(!ac.isAlive())
if
found.remove(key);
found
}
catch(RemoteException re)
catch
{
System.out.println("findServices() " + ac.getClass().getName()
System
+ " is dead");
found.remove(key);
found
}
}
// wieder suchen
searchClasses();
searchClasses
}
/**
* Sucht alle bekannten Lookup Services nach den verlangten Klassen a b
und fügt
füg
* sie ggf. zu dem Vector hinzu.
hinzu
*/
public void searchClasses()
{
System.out.println("searchClasses() invoked");
System
// Liste aller gesuchten Klassen durchgehen
Enumeration enum = searched.elements();
while(enum.hasMoreElements())
while
{
// Klassennamen aus dem Vektor lesen
String classname = (String) enum.nextElement();
if
if(found.get(classname)
== null)
{
System.out.println("searchClasses() no " + classname + " found
System
yet, looking for an instance");
Class[] classes = null;
Class
try
{
Class[] tmp = {Class.forName(classname)};
Class
// stupid java compiler
classes = tmp;
}
catch(ClassNotFoundException cnfe)
catch
{
// hm. pech
System.out.println("searchClasses() ClassNotFoundException
System
while looking for " + classname);
continue;
continue
}
// template erstellen
ServiceTemplate template = new ServiceTemplate(null, classes,
null);
Enumeration reg_enum = registrars.elements();
while
while(reg_enum.hasMoreElements())
{
System.out.println("searchClasses() checking a lookup
System
service");
ServiceRegistrar reg = (ServiceRegistrar)
reg_enum.nextElement();
ServiceMatches matches = null;
try
{
// alle Dienste die der Lookup Service hat und die auf
das Template passen lesen
// max. 100 services
matches = reg.lookup(template, 100);
}
catch(RemoteException re)
catch
{
// tscha. pech.
}
if
if(matches
!= null)
{
System.out.println("searchClasses() " +
System
matches.totalMatches + " matches found");
// durch alle gefundenen Services laufen
for(int j=0; j<matches.totalMatches; j++)
for
{
// service auslesen
ServiceItem item = matches.items[j];
if(item != null && item.service == null)
if
System.out.println("searchClasses() item.service ==
System
null");
// ggf. in die found hashtable schreiben
if(item != null && found.get(classname) == null &&
if
item.service != null)
{
// Prüfen ob der Service lebt
try
{
AliveCheckable ac = (AliveCheckable)
item.service;
if
if(!ac.isAlive())
{
// Hm. Tot.
System.out.println("searchClasses()
System
item.service.isAlive() == false");
continue;
continue
}
}
catch(ClassCastException cce)
catch
{
}
catch(RemoteException re)
catch
{
// Hm. Tot.
System.out.println("searchClasses()
System
item.service.isAlive() threw RemoteException");
continue;
continue
}
found.put(classname, item.service);
found
}
}
}
}
}
}
}
/**
* Error-Melder
Error-Melde
*
* @param classname der Name der Klasse bei der ein Fehler besteht .
*/
private void reportError(String classname)
{
String ls = (String) last_status.get(classname);
if(ls.equals(STATUS_OK) || (ls.equals(STATUS_ERROR) &&
if
System.currentTimeMillis() - start_time > timeout))
if(!classname.equals(MAIL_SERVER))
if
new MailerThread(STATUS_MAIL_RECIPIENT, "[mm-projekt] " +
classname + " is null", "previous status: " + ls).start();
last_status.put(classname, STATUS_ERROR);
last_status
}
/**
* Dieser Thread wird gestartet wenn ein Fehler aufgetreten ist. E r
versucht mit Hilfe
* des Mailservice eine Mail an den Systemadministrator zu verschicken .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
private class MailerThread extends Thread
{
private String rcp_email = null;
private String subject = null;
private String body = null;
public MailerThread(String rcp_email, String subject, String body)
{
this.rcp_email = rcp_email;
this
this.subject = subject;
this
this.body = body;
this
}
public void
{
// * * *
// * * *
// * * *
// * * *
// * * *
}
run()
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
}
/**
* ies ist der Thread, der nach den gesuchten Klassen sucht un d
überwacht,
* ob die Klassen verschwunden sind.
sind
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
private class SearcherThread extends Thread
{
public SearcherThread()
{}
public void run()
{
boolean all_ok = false;
while
while(true)
{
System.out.println("SearcherThread.run() main loop");
System
try
{
if(all_ok)
if
{
all_ok = checkServices();
if(all_ok)
if
sleep(30000);
sleep
}
else
{
findServices();
findServices
all_ok = true;
sleep(3000);
sleep
}
}
catch(InterruptedException ie)
catch
{
}
}
}
}
}
b.) mm.services.chat
Dieses Paket enthält alle Klassen des Chat-Service.
Klasse
Chat
ChatController
ChatEventData
ChatIn
ChatMain
ChatOut
ChatRoom
ChatServer
PageParameters
SessionManager
Bedeutung
Remote Interface des Chat-Servers
Rezipient für Chat-Events im Webserver
Daten für die Event-Registrierung
Servlet, das Eingabezeilen vom Benutzer
entgegennimmt
Instantiiert einen Chat-Service und registriert
ihn beim Lookup-Service
Servlet, das die Ausgabe des Chats erledigt
Ein Chat-Raum
Die Implementation des Chat-Servers
Hilfsklasse, die die Auswertung von GETund POST-Parametern vereinfacht
Managed ChatSessions
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface mm.services.chat.Chat
public abstract interface Chat
extends java.rmi.Remote, mm.tools.AliveCheckable
Ueber dieses Interface koennen Methoden des ChatServers aufgerufen
werden.
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
addChatListener(RemoteEventListener, MarshalledObject)
Interface zur EventRegistration der Clients
chatRoomCreated(String)
Ueberprueft, ob der angegebene Chat-Room existiert
createChatRoom(String)
Erzeugt einen Chat-Room
deleteChatRoom(String)
Loescht den angegebenen Chat-Room
getLastLines(int, String)
Gibt die letzten Chatzeilen zurueck.
getLine(String)
Gibt die letzte Chat-Line des angegebenen Chat-Rooms zurueck
insertLine(String, String)
Fuegt eine Chat-Line beim angegebenen Chat-Room ein
insertLine
public void insertLine(java.lang.String cr,
java.lang.String line) throws java.rmi.RemoteException
Fuegt eine Chat-Line beim angegebenen Chat-Room ein
Parameters:
cr - Name des Chat-Rooms
line - Die Chat-Line fuer den Chat-Room
Returns:
void
getLine
public java.lang.String getLine(java.lang.String cr) throws java.rmi.RemoteException
Gibt die letzte Chat-Line des angegebenen Chat-Rooms zurueck
Parameters:
cr - Name des Chat-Rooms
Returns:
Die letzte Zeile des angegebenen ChatRooms
getLastLines
public java.util.Vector getLastLines(int anz,
java.lang.String cr) throws java.rmi.RemoteException
Gibt die letzten Chatzeilen zurueck. Anzahl der Zeilen kann
uebergeben werden.
Parameters:
anz - Anzahl der Zeilen
cr - Chatroom
Returns:
String[] Array mit den letzten Chatzeilen
createChatRoom
public void createChatRoom(java.lang.String cr) throws java.rmi.RemoteException
Erzeugt einen Chat-Room
Parameters:
cr - Name des Chat-Rooms
Returns:
void
deleteChatRoom
public void deleteChatRoom(java.lang.String cr) throws java.rmi.RemoteException
Loescht den angegebenen Chat-Room
Parameters:
cr - Name des Chat-Rooms
Returns:
void
chatRoomCreated
public boolean chatRoomCreated(java.lang.String cr) throws java.rmi.RemoteException
Ueberprueft, ob der angegebene Chat-Room existiert
Parameters:
cr - Name des Chat-Rooms
Returns:
boolean true: ChatRoom existiert, false: ChatRoom existiert nicht
addChatListener
public net.jini.core.event.EventRegistration addChatListener(net.jini.core.event.RemoteEve
java.rmi.MarshalledObject handbackObject) throws
Interface zur EventRegistration der Clients
Parameters:
addChatListener - Client uebergibt RemoteEventListener. An diesen
Listener wird der Event geschickt.
handbackObject - Object das vom Client uebergeben wird und
spaeter vom Listener des Clients mitgeschickt und ausgewertet
werden kann.
Returns:
EventRegistration
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.chat;
import java.util.Vector;
import java.rmi.MarshalledObject;
import java.rmi.Remote;
import java.rmi.RemoteException;
import net.jini.core.event.EventRegistration;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.lease.LeaseDeniedException;
import mm.tools.AliveCheckable;
/**
* Ueber dieses Interface koennen Methoden des ChatServer s
* aufgerufen werden.
werden
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*/
public interface Chat extends Remote, AliveCheckable {
/**
* Fuegt eine Chat-Line beim angegebenen Chat-Room ei n
*
* @param cr Name des Chat-Rooms
Chat-Room
* @param line Die Chat-Line fuer den Chat-Roo m
* @return void
voi
*/
public void insertLine(String cr, String line) throws RemoteException;
/**
* Gibt die letzte Chat-Line des angegebenen Chat-Rooms zuruec k
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return Die letzte Zeile des angegebenen ChatRoom s
*/
public String getLine(String cr) throws RemoteException;
/**
* Gibt die letzten Chatzeilen zurueck. Anzahl der Zeile n
* kann uebergeben werden.
werden
* @param anz Anzahl der Zeilen
Zeile
* @param cr
Chatroo
Chatroom
* @return String[]
Array mit den letzten <anz> Chatzeilen
Chatzeile
*/
public Vector getLastLines(int anz,String cr) throws RemoteException;
/**
* Erzeugt einen Chat-Room
Chat-Roo
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return void
voi
*/
public void createChatRoom(String cr) throws RemoteException;
/**
* Loescht den angegebenen Chat-Room
Chat-Roo
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return void
voi
*/
public void deleteChatRoom(String cr) throws RemoteException;
/**
* Ueberprueft, ob der angegebene Chat-Room existier t
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return boolean true: ChatRoom existiert, false: ChatRoom existier t
nicht
nich
*/
public boolean chatRoomCreated(String cr) throws RemoteException;
/** Interface zur EventRegistration der Clients
*
* @param addChatListener Client uebergibt RemoteEventListener. An diese n
* Listener wird der Event geschickt.
geschickt
* @param handbackObject
Object das vom Client uebergeben wird un
und
spaeter vom
vo
* Listener des Clients mitgeschickt und ausgewertet werden kann .
* @return EventRegistration
EventRegistratio
*/
public EventRegistration addChatListener( RemoteEventListener
chatListener, MarshalledObject handbackObject ) throws
RemoteException, LeaseDeniedException;
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatController
mm.services.chat.ChatController
public class ChatController
Der ChatController uebernimmt die Registrierung fuer das RemoteEvent,
welches beim einfuegen einer neuen Chatzeile auftritt und schreibt diese in
einen Vector.
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
ChatController(String, Chat)
Konstruktor: Hier findet die Registrierung fuer den RemoteEvent via
addChatListener() statt, um Notifikationen ueber neu eingefuegte
Chat-Zeilen im entsprechenden Chat-Room zu erhalten.
getHashtable()
Die Methode getHashTable gibt die Hashtable zurueck in der die
Vectoren der einzelnen Chat-Clients mittels dem key "threadCount"
eindeutig abgelegt sind.
incrementThreadCount()
Die Methode incrementThreadCount erhoeht den "long" Wert
"threadCount" um 1.
notify(LeaseRenewalEvent)
Die Notify-Methode befaehigt den LeaseListener ein auftretendes
LeaseRenewalEvent zu verarbeiten.
notify(RemoteEvent)
Diese Methode wird aufgerufen sobald ein RemoteEvent auftritt, fuer
welches Interesse angemeldet wurde.
ChatController
public ChatController(java.lang.String room,
Chat ourServer)
Konstruktor: Hier findet die Registrierung fuer den RemoteEvent via
addChatListener() statt, um Notifikationen ueber neu eingefuegte ChatZeilen im entsprechenden Chat-Room zu erhalten. Beim instanziieren des
ChatControllers wird der ChatServer und der Name des gewuenschten
ChatRooms uebergeben.
Parameters:
String - Der Name des ChatRooms
Chat - Der ChatServer
incrementThreadCount
public long incrementThreadCount()
Die Methode incrementThreadCount erhoeht den "long" Wert
"threadCount" um 1. Damit wird eine eindeutige Zuordnung zwischen
threadCount und Client erreicht.
getHashtable
public java.util.Hashtable getHashtable()
Die Methode getHashTable gibt die Hashtable zurueck in der die
Vectoren der einzelnen Chat-Clients mittels dem key "threadCount"
eindeutig abgelegt sind.
Returns:
Hashtable Die Hashtable mit den Vectoren
notify
public void notify(com.sun.jini.lease.LeaseRenewalEvent lostLease)
Die Notify-Methode befaehigt den LeaseListener ein auftretendes
LeaseRenewalEvent zu verarbeiten.
Parameters:
LeaseRenewalEvent - Das aufgetretene LeasRenewalEvent
Returns:
void
notify
public void notify(net.jini.core.event.RemoteEvent e)
Diese Methode wird aufgerufen sobald ein RemoteEvent auftritt, fuer
welches Interesse angemeldet wurde.
Parameters:
e - das erzeugte RemoteEvent
Returns:
void
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package
mm.services.chat;
mm
import java.util.Hashtable;
import java.util.Vector;
import java.util.Iterator;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStream;
import
import
import
import
import
java.rmi.RMISecurityManager;
java.rmi.MarshalledObject;
java.rmi.Remote;
java.rmi.RemoteException;
java.rmi.server.UnicastRemoteObject;
import
import
import
import
import
import
import
import
import
net.jini.core.entry.Entry;
net.jini.lookup.entry.Name;
net.jini.core.lookup.ServiceTemplate;
net.jini.core.lookup.ServiceRegistrar;
net.jini.core.discovery.LookupLocator;
net.jini.core.event.RemoteEventListener;
net.jini.core.event.RemoteEvent;
net.jini.core.event.EventRegistration;
net.jini.core.lease.LeaseDeniedException;
import com.sun.jini.lease.LeaseListener;
import com.sun.jini.lease.LeaseRenewalEvent;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import mm.services.chat.Chat;
/**
* Der ChatController uebernimmt die Registrierung fuer das RemoteEvent ,
* welches beim einfuegen einer neuen Chatzeile auftritt und schreibt
* diese in einen Vector.
Vector
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*
**/
public class ChatController implements RemoteEventListener, LeaseListener {
// ChatServer
private Chat chatIf;
// EventRegistration beim ChatServer
private EventRegistration chatReg = null;
// Ist registriert "false" oder "true"
private boolean isRegistered = false;
// Unser ChatRoom fuer den wir Verantwortlich sind.
private String chatRoom = null;
// Counter fuer die Clients
private long threadCount = 0;
// Hashtable mit den Clients als Vector
private Hashtable jspVectors = null;
/**
* Konstruktor:
Konstruktor
* Hier findet die Registrierung fuer den RemoteEvent vi a
addChatListener() statt,
statt
* um Notifikationen ueber neu eingefuegte Chat-Zeilen im entsprechende n
Chat-Room
Chat-Roo
* zu erhalten.
erhalten
* Beim instanziieren des ChatControllers wird der ChatServer und
* der Name des gewuenschten ChatRooms uebergeben.
uebergeben
*
* @param String
Der Name des ChatRooms
ChatRoom
* @param Chat
Der ChatServer
ChatServe
*
**/
public ChatController(String room, Chat ourServer) {
chatRoom = room;
chatIf = ourServer;
jspVectors = new Hashtable();
if (chatIf != null) {
try {
RemoteEventListener notifyMe = (RemoteEventListener)
UnicastRemoteObject.exportObject(this);
MarshalledObject handbackObject = new
MarshalledObject(chatRoom);
chatReg = chatIf.addChatListener(this, handbackObject);
isRegistered = true;
}
catch (LeaseDeniedException lde) {
lde.printStackTrace();
lde
}
catch (IOException ioe ) {
ioe.printStackTrace();
ioe
}
}
else
System.exit(1);
System
}
/**
* Die Methode incrementThreadCount erhoeht den "long" Wert "threadCount "
um 1.
1
* Damit wird eine eindeutige Zuordnung zwischen threadCount und Clien t
erreicht.
erreicht
*
* @ return long
Gibt den um eins erhoehten Wert von threadCoun t
zurueck
zuruec
*
**/
public long incrementThreadCount() {
return ++threadCount;
}
/**
* Die Methode getHashTable gibt die Hashtable zurueck
* in der die Vectoren der einzelnen Chat-Clients mittels dem ke y
"threadCount"
"threadCount
* eindeutig abgelegt sind.
sind
*
* @return Hashtable Die Hashtable mit den Vectoren
Vectore
*
**/
public Hashtable getHashtable() {
return jspVectors;
}
/**
* Die Notify-Methode befaehigt den LeaseListener ein
ei
* auftretendes LeaseRenewalEvent zu verarbeiten.
verarbeiten
*
* @param LeaseRenewalEvent Das aufgetretene LeasRenewalEvent
LeasRenewalEven
* @return void
voi
*
**/
public void notify(LeaseRenewalEvent lostLease) {
Exception deniedReason = lostLease.getException();
if (deniedReason != null )
System.out.println( "Lease verloren, weil: " + deniedReason
System
);
else
System.out.println( "Lease verloren, keine Ursache
System
feststellbar" );
}
/**
* Diese Methode wird aufgerufen sobald ein RemoteEvent auftritt ,
* fuer welches Interesse angemeldet wurde.
wurde
*
* @param e
das erzeugte RemoteEvent
RemoteEven
* @return void
voi
*
**/
public void notify(RemoteEvent e) {
try {
String line = e.getRegistrationObject().get().toString();
Iterator lineIter;
synchronized (jspVectors) {
lineIter = jspVectors.values().iterator();
}
while (lineIter.hasNext()) {
((Vector
((
Vector) lineIter.next()).add(line);
);
System.out.println("Die eingefuegte ChatLine: " + line );
System
}
}
catch (Exception re) {
System.out.println("insertLine fehlgeschlagen:");
System
re.printStackTrace();
re
}
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatEventData
java.lang.Object
|
+----mm.services.chat.ChatEventData
public class ChatEventData
extends java.lang.Object
Objekte dieser Klasse enthalten alle notwendigen Daten fuer die EventRegistrierung.
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
ChatEventData(long, RemoteEventListener, MarshalledObject)
Konstruktor der Klasse ChatEventData
getExpiration()
Rueckgabe der Lease-Dauer
getHandbackObject()
Rueckgabe des handbackObjects.
notifyListener(long, Object, long, MarshalledObject)
Erzeugung eines RemoteEvent und Aufruf der Notify-Methode des
registrierten RemoteEventListeners
setDuration(long)
Setzen der neuen Lease-Dauer
setExpiration(long)
Eintragen einer neuen Lease-Dauer
ChatEventData
public ChatEventData(long leaseExpiration,
net.jini.core.event.RemoteEventListener eventListener,
java.rmi.MarshalledObject handbackObject)
Konstruktor der Klasse ChatEventData
Parameters:
leaseExpiration - Lease-Dauer
eventListener - Objekt, das sich fuer das Event registriert
handbackObject - Objekt, das beim Auftreten des Events wieder
zurueck gegeben wird
getHandbackObject
public java.rmi.MarshalledObject getHandbackObject()
Rueckgabe des handbackObjects.
Returns:
MarshalledObject Das handbackObject
getExpiration
public long getExpiration()
Rueckgabe der Lease-Dauer
Returns:
leaseExpiration Dauer der Lease
setExpiration
public void setExpiration(long newLeaseExpiration)
Eintragen einer neuen Lease-Dauer
Parameters:
newLeaseExpiration - Die neue Lease-Dauer
Returns:
void
setDuration
public void setDuration(long newLeaseDuration)
Setzen der neuen Lease-Dauer
Parameters:
newLeaseDuration Returns:
void
notifyListener
public void notifyListener(long eventID,
java.lang.Object eventSource,
long eventSequenceNumber,
java.rmi.MarshalledObject chatLine) throws net.jini.core.event.
Erzeugung eines RemoteEvent und Aufruf der Notify-Methode des
registrierten RemoteEventListeners
Parameters:
eventID - Die ID das aufgetretenen Events
eventSource - Event-Generator
eventSequenceNumber - Sequenz-Nummer des aufgetretenen Events
chatLine - Das Objekt wird mit der Notify-Methode an den Listener
zurueckgeliefert
Returns:
leaseExpiration Dauer der Lease
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.chat;
import
import
import
import
java.rmi.MarshalledObject;
java.rmi.RemoteException;
java.util.List;
java.util.Map;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.event.UnknownEventException;
/**
* Objekte dieser Klasse enthalten alle notwendigen Daten fue r
* die Event-Registrierung.
Event-Registrierung
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*
**/
public class ChatEventData {
MarshalledObject handbackObject = null;
RemoteEventListener eventListener = null;
long leaseExpiration = 0;
/**
* Konstruktor der Klasse ChatEventData
ChatEventDat
*
* @param leaseExpiration Lease-Dauer
Lease-Daue
* @param eventListener Objekt, das sich fuer das Event registrier t
* @param handbackObject Objekt, das beim Auftreten des Events wiede r
zurueck gegeben wird
wir
*
**/
public ChatEventData(long leaseExpiration, RemoteEventListener
eventListener,MarshalledObject handbackObject) {
this.leaseExpiration = leaseExpiration;
this
this.handbackObject = handbackObject;
this
this.eventListener = eventListener;
this
}
/**
* Rueckgabe des handbackObjects.
handbackObjects
*
* @return MarshalledObject Das handbackObject
handbackObjec
*
**/
public MarshalledObject getHandbackObject() {
return handbackObject;
}
/**
* Rueckgabe der Lease-Dauer
Lease-Daue
*
* @return leaseExpiration Dauer der Lease
Leas
*
**/
public long getExpiration() {
return leaseExpiration;
}
/**
* Eintragen einer neuen Lease-Dauer
Lease-Daue
*
* @param newLeaseExpiration Die neue Lease-Dauer
Lease-Daue
* @return void
voi
*
**/
public void setExpiration(long newLeaseExpiration) {
leaseExpiration = newLeaseExpiration;
}
/**
* Setzen der neuen Lease-Dauer
Lease-Daue
*
* @param newLeaseDuration
newLeaseDuratio
* @return void
voi
*
**/
public void setDuration(long newLeaseDuration) {
setExpiration(newLeaseDuration + System.currentTimeMillis());
setExpiration
}
/**
* Erzeugung eines RemoteEvent und Aufruf der Notify-Methode des
* registrierten RemoteEventListeners
RemoteEventListener
*
* @param eventID Die ID das aufgetretenen Event s
* @param eventSource Event-Generator
Event-Generato
* @param eventSequenceNumber Sequenz-Nummer des aufgetretenen Events
Event
* @param chatLine Das Objekt wird mit der Notify-Methode an den Listene r
zurueckgeliefert
zurueckgeliefer
* @return leaseExpiration Dauer der Lease
Leas
*
**/
public void notifyListener(long eventID, Object eventSource, long
eventSequenceNumber,MarshalledObject chatLine) throws
UnknownEventException, RemoteException {
RemoteEvent eventData = new RemoteEvent(eventSource, eventID,
eventSequenceNumber, chatLine);
eventListener.notify(eventData);
eventListener
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatIn
java.lang.Object
|
+----mm.webserver.jsp.JspSuperClass
|
+----mm.services.chat.ChatIn
public class ChatIn
extends mm.webserver.jsp.JspSuperClass
Das ChatIn-Servlet dient zur Eingabe der Chatzeilen, welche an den
ChatServer gesendet werden.
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
ChatIn()
_jspService(HttpServletRequest, HttpServletResponse)
In _jspService() wird ueber das HttpServletResponse-Objekt HTMLCode an den Client gesendet und die Chat-Zeile (mit Farbe und NickName) via insertLine() an den Server geschickt.
jspInit()
In jspInit() wird der Chat-Server mit Hilfe des Service-Controllers
gesucht und ein Chat-Room erzeugt.
ChatIn
public ChatIn()
jspInit
public void jspInit()
In jspInit() wird der Chat-Server mit Hilfe des Service-Controllers
gesucht und ein Chat-Room erzeugt.
Returns:
void
Overrides:
jspInit in class mm.webserver.jsp.JspSuperClass
_jspService
public void _jspService(javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse res)
In _jspService() wird ueber das HttpServletResponse-Objekt HTMLCode an den Client gesendet und die Chat-Zeile (mit Farbe und Nick-Name)
via insertLine() an den Server geschickt.
Parameters:
req - Das HttpServletRequest-Objekt
res - Das HttpServletResponse-Objekt
Returns:
void
Overrides:
_jspService in class mm.webserver.jsp.JspSuperClass
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package
mm.services.chat;
mm
import java.util.Hashtable;
import java.util.Vector;
import java.util.Iterator;
import
import
import
import
java.io.IOException;
java.io.PrintWriter;
java.io.OutputStream;
java.io.BufferedReader;
import java.rmi.RemoteException;
import
import
import
import
import
import
import
import
import
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;
javax.servlet.ServletException;
javax.servlet.ServletContext;
javax.servlet.ServletInputStream;
javax.servlet.http.HttpUtils;
javax.servlet.RequestDispatcher;
javax.servlet.jsp.JspPage;
import mm.webserver.jsp.JspSuperClass;
import mm.jini.ServiceController;
/**
* Das ChatIn-Servlet dient zur Eingabe der Chatzeilen ,
* welche an den ChatServer gesendet werden .
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*/
public class ChatIn extends JspSuperClass {
Chat chatServer
chatServer=null;
/**
* In jspInit() wird der Chat-Server mit Hilfe des Service-Controller s
* gesucht und ein Chat-Room erzeugt.
erzeugt
*
* @return void
voi
*/
public void jspInit() {
chatServer = (Chat) service_controller.getService(CHAT_SERVER);
int i = 0;
while (chatServer==null && i<10) {
chatServer = (Chat) service_controller.getService(CHAT_SERVER);
i++;
try {
Thread.currentThread().sleep(500);
Thread
}
catch (InterruptedException ie) {
ie.printStackTrace();
ie
}
}
if (chatServer!=null) {
try {
chatServer.createChatRoom("room2");
chatServer
}
catch (RemoteException re) {
re.printStackTrace();
re
}
}
}
/**
* In _jspService() wird ueber das HttpServletResponse-Objekt HTML-Code a n
den Client gesendet
gesende
* und die Chat-Zeile (mit Farbe und Nick-Name) via insertLine() an de n
Server geschickt.
geschickt
*
* @param req Das HttpServletRequest-Objekt
HttpServletRequest-Objek
* @param res Das HttpServletResponse-Objekt
HttpServletResponse-Objek
* @return void
voi
*/
public void _jspService(HttpServletRequest req, HttpServletResponse res)
{
HttpSession session = null;
PrintWriter out = null;
Hashtable old_data = new Hashtable();
session = req.getSession(false);
try {
out = res.getWriter();
}
catch (IOException ioe) {
ioe.printStackTrace();
ioe
}
res.setContentType("text/html");
res
out.println("<html><head><title>ChatEingabe</title><head><body
out
bgcolor=\"#FFFFFF\">");
out.println("<font color=\"#000000\" face=\"trebuchet ms, verdana,
out
arial\" size=\"+2\"><b>Chat-Zeilen:</b></font><p>");
out.println("<form name=\"inputLine\"
out
action=\"http:
://motion.ghb.fh-furtwangen.de:8001/servlet/ChatIn\"
method=\"post\">");
out.println("<input type=\"text\" name=\"chatLine\" size=\"60\"
out
maxlength=\"500\">");
out.println("<input type=\"submit\">");
out
out.println("</form></body></html>");
out
out.flush();
out
PageParameters params = new PageParameters(req);
String chatLine = params.getString("chatLine");
if (chatLine.length() != 0) {
if (chatServer!=null) {
try{
try
if (session==null){
String insertString = new String("<font color=\"#000000\">
guest > " + chatLine);
chatServer.insertLine("room2",insertString);
chatServer
}
else {
String chatColor = (String) session.getValue("Farbe");
String chatName = (String) session.getValue("NickName");
String color = null;
if( chatColor.equals("rot") ){
if
color = new String("<font color=\"#FF0000\">");
}
else if(chatColor.equals("blau")) {
color = new String("<font color=\"#0000FF\">");
}
else if(chatColor.equals("gruen")) {
color = new String("<font color=\"#00FF00\">");
}
else if(chatColor.equals("schwarz")) {
color = new String("<font color=\"#000000\">");
}
String insertString= new String(color + chatName +" > " +
chatLine);
chatServer.insertLine("room2",insertString);
chatServer
}
}
catch (RemoteException re) {
re.printStackTrace();
re
}
}
}
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatMain
mm.services.chat.ChatMain
public class ChatMain
Die ChatMain-Klasse dient dazu den Chat-Server zu starten und an dem
Jini-LookUp-Service mittels eines JoinManagers zu registrieren.
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
ChatMain()
main(String[])
serviceIDNotify(ServiceID)
Bei erfolgreicher Registrierung des Chat-Servers erhaelt dieser eine
eindeutige ServiceID
ChatMain
public ChatMain()
main
public static void main(java.lang.String args[]) throws java.lang.Exception
serviceIDNotify
public void serviceIDNotify(net.jini.core.lookup.ServiceID id)
Bei erfolgreicher Registrierung des Chat-Servers erhaelt dieser eine
eindeutige ServiceID
Parameters:
id - Die ServiceID des registrierten Chat-Servers
Returns:
void
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.chat;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
import java.util.Hashtable;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceID;
import net.jini.lookup.entry.Name;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lease.LeaseRenewalManager;
/**
* Die ChatMain-Klasse dient dazu den Chat-Server zu starte n
* und an dem Jini-LookUp-Service mittels eines JoinManagers z u
registrieren.
registrieren
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*
**/
public class ChatMain implements ServiceIDListener {
private ServiceID
chatID;
chatID
public ChatMain() {}
public static void main(String[] args) throws Exception {
System
System.setSecurityManager
(new RMISecurityManager ());
ChatServer testServer = new ChatServer();
Entry
Entry[]
attribs = new Entry[1];
attribs[0]= new Name("ChatServer");
attribs
JoinManager testManager = new JoinManager
(
testServer,
testServer
attribs,
attribs
new ChatMain(),
new LeaseRenewalManager()
);
System.out.println ("ChatServer ist jetzt bereit.");
System
new Thread(testServer).start();
}
/**
* Bei erfolgreicher Registrierung des Chat-Servers
Chat-Server
* erhaelt dieser eine eindeutige ServiceID
ServiceI
*
* @param id
Die ServiceID des registrierten Chat-Server s
* @return void
voi
*
**/
public void serviceIDNotify(ServiceID id) {
chatID=id;
chatID
System.out.println("ChatserverID: " + chatID);
System
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatOut
java.lang.Object
|
+----mm.webserver.jsp.JspSuperClass
|
+----mm.services.chat.ChatOut
public class ChatOut
extends mm.webserver.jsp.JspSuperClass
Das ChatOut-Servlet dient der Anzeige aller Chat-Zeilen fuer die Clients
Version:
1.0
Author:
Oliver Hilss und Mirko Tochtermann
ChatOut()
_jspService(HttpServletRequest, HttpServletResponse)
In _jspService() werden zunaechst eventuell bereits existierende ChatZeilen an den Client gesendet.
jspInit()
In jspInit() wird der Chat-Server mit Hilfe des Service-Controllers
gesucht und ein ChatController fuer den entsprechenden Chat-Room
und Chat-Server erzeugt.
ChatOut
public ChatOut()
jspInit
public void jspInit()
In jspInit() wird der Chat-Server mit Hilfe des Service-Controllers
gesucht und ein ChatController fuer den entsprechenden Chat-Room und
Chat-Server erzeugt.
Returns:
void
Overrides:
jspInit in class mm.webserver.jsp.JspSuperClass
_jspService
public void _jspService(javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse res)
In _jspService() werden zunaechst eventuell bereits existierende
Chat-Zeilen an den Client gesendet. Durch eine Endlos-Schleife wird
garantiert, dass der HTTP-Stream "offen" bleibt und somit staendig neue
Chat-Zeilen eingefuegt werden koennen. Eine Java-Skript-Funktion sorgt
dafuer, dass das Fenster stets heruntergescrollt wird, wenn neue Zeilen
eintreffen.
Returns:
void
Overrides:
_jspService in class mm.webserver.jsp.JspSuperClass
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package
mm.services.chat;
mm
import java.util.Hashtable;
import java.util.Vector;
import java.util.Iterator;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStream;
import
import
import
import
import
java.rmi.RMISecurityManager;
java.rmi.MarshalledObject;
java.rmi.Remote;
java.rmi.RemoteException;
java.rmi.server.UnicastRemoteObject;
import
import
import
import
import
import
import
import
import
net.jini.core.entry.Entry;
net.jini.lookup.entry.Name;
net.jini.core.lookup.ServiceTemplate;
net.jini.core.lookup.ServiceRegistrar;
net.jini.core.discovery.LookupLocator;
net.jini.core.event.RemoteEventListener;
net.jini.core.event.RemoteEvent;
net.jini.core.event.EventRegistration;
net.jini.core.lease.LeaseDeniedException;
import com.sun.jini.lease.LeaseListener;
import com.sun.jini.lease.LeaseRenewalEvent;
import
import
import
import
import
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;
javax.servlet.ServletException;
javax.servlet.ServletContext;
import mm.webserver.jsp.JspSuperClass;
/**
* Das ChatOut-Servlet dient der Anzeige aller Chat-Zeilen fue r
* die Clients
Client
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochterman n
*
**/
public class ChatOut extends JspSuperClass {
Chat chatServer
chatServer;
ChatController cc = null;
int i = 0;
/**
* In jspInit() wird der Chat-Server mit Hilfe des Service-Controller s
* gesucht und ein ChatController fuer den entsprechenden Chat-Roo m
* und Chat-Server erzeugt.
erzeugt
*
* @return void
voi
**/
public void jspInit() {
while (chatServer==null && i<10) {
chatServer = (Chat) service_controller.getService(CHAT_SERVER);
try {
Thread.currentThread().sleep(500);
Thread
i++;
}
catch (InterruptedException ie) {
ie.printStackTrace();
ie
}
}
cc = (ChatController) context.getAttribute("chatController.room2");
if (cc == null) {
synchronized(this) {
synchronized
cc = new ChatController("room2", chatServer);
context.setAttribute("chatController.room2", cc);
context
}
}
}
/**
* In _jspService() werden zunaechst eventuell bereits existierend e
Chat-Zeilen an
a
* den Client gesendet.
gesendet
* Durch eine Endlos-Schleife wird garantiert, dass der HTTP-Strea m
"offen" bleibt
bleib
* und somit staendig neue Chat-Zeilen eingefuegt werden koennen.
* Eine Java-Skript-Funktion sorgt dafuer, dass das Fenster stet s
heruntergescrollt wird,
wird
* wenn neue Zeilen eintreffen.
eintreffen
*
* @return void
voi
*
**/
public void _jspService(HttpServletRequest req, HttpServletResponse res)
{
Hashtable
hash = null;
Long user = null;
Vector ourVector = new Vector();
PrintWriter out = null;
Vector buffer = null;
hash = (Hashtable) cc.getHashtable();
user = new Long(cc.incrementThreadCount());
hash.put(user,ourVector);
hash
try {
out = res.getWriter();
}
catch (IOException ioe) {
ioe.printStackTrace();
ioe
}
res.setContentType("text/html");
res
try {
buffer = chatServer.getLastLines(20,"room2");
}
catch (RemoteException re) {
re.printStackTrace();
re
}
out.println("<html><head><title>MM Chat</title><script><!--\n");
out
out
out.println("function
doScroll(){timer=setTimeout(\"doScroll()\",
50);window.scrollBy(0,8);window.scrollBy(0,4);window.scrollBy(0,2);window.s
crollBy(0,1);}\n");
out.println("doScroll();\n");
out
out.println("//--></script>\n");
out
out.println("</head><body bgcolor=\"#FFFFFF\">");
out
out.println("<font color=\"#000000\" face=\"trebuchet ms, verdana,
out
arial\" size=\"+2\"><b>Chat-Zeilen:</b></font><p>");
out.flush();
out
// Ausgeben bereits existierender Chat-Zeilen
if (buffer != null) {
for (int k=0;k < buffer.size();k++) {
out.println(buffer.elementAt(k) + "<br>"+
out
}
}
out.flush();
out
"\n");
while (true) {
try {
Thread.currentThread().sleep(100);
Thread
}
catch (InterruptedException ie) {
ie.printStackTrace();
ie
}
if (ourVector.isEmpty() == false) {
for (int y=0;y < ourVector.size();y++) {
out.println( (String) ourVector.elementAt(y)+ "<br>" + "\n"
out
);
out.flush();
out
}
}
else {
out.println(" ");
out
}
ourVector.removeAllElements();
ourVector
out.flush();
out
}
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatRoom
java.lang.Object
|
+----mm.services.chat.ChatRoom
public class ChatRoom
extends java.lang.Object
Diese Klasse implementiert einen oeffentlichen ChatRoom oder einen
Gruppen-ChatRoom.
Version:
1.0
Author:
Mirko Tochtermann und Oliver Hilss
ChatRoom(String)
Konstruktor gibt dem Chat-Room seinen Namen
getChatLine()
Gibt die letzte Chat-Line des eigenen Chat-Rooms zurueck
getChatLines(int)
Gibt die letzen Chatzeilen aus.
insertChatLine(String)
Setzt eine Chat-Line in den eigenen Chat-Room
ChatRoom
public ChatRoom(java.lang.String name)
Konstruktor gibt dem Chat-Room seinen Namen
Parameters:
name - Name des Chat-Rooms
insertChatLine
public void insertChatLine(java.lang.String line)
Setzt eine Chat-Line in den eigenen Chat-Room
Parameters:
line - Die einzusetzende Chat-Line
Returns:
void
getChatLine
public java.lang.String getChatLine()
Gibt die letzte Chat-Line des eigenen Chat-Rooms zurueck
Returns:
Die letzte Zeile im Chat-Room
getChatLines
public java.util.Vector getChatLines(int anz)
Gibt die letzen Chatzeilen aus.
Parameters:
anz - Anzahl der auszugebenden Chatzeilen
Returns:
String[] Array der letzten Chatzeilen
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.chat;
import java.util.Vector;
import java.util.Date;
/**
* Diese Klasse implementiert einen oeffentlichen ChatRoo m
* oder einen Gruppen-ChatRoom.
Gruppen-ChatRoom
*
* @version 1.0
1.
* @author Mirko Tochtermann und Oliver Hils s
*
**/
public class ChatRoom {
private String name = null;
private Vector lines = null;
private Vector time = null;
/**
* Konstruktor gibt dem Chat-Room seinen Namen
Name
*
* @param name Name des Chat-Rooms
Chat-Room
*
**/
public ChatRoom(String name) {
lines = new Vector();
time = new Vector();
this.name=name;
this
new Cleanup().start();
}
/**
* Setzt eine Chat-Line in den eigenen Chat-Roo m
*
* @param line Die einzusetzende Chat-Line
Chat-Lin
* @return void
voi
*
**/
public synchronized void insertChatLine(String line) {
time.add(new Date());
time
lines.add(line);
lines
}
/**
* Gibt die letzte Chat-Line des eigenen Chat-Rooms zuruec k
*
* @return Die letzte Zeile im Chat-Room
Chat-Roo
*
**/
public String getChatLine() {
if (!lines.isEmpty())
return (String) lines.lastElement();
return null;
;
}
/**
* Gibt die letzen <anz> Chatzeilen aus.
aus
*
* @param anz
Anzahl der auszugebenden Chatzeilen
Chatzeile
* @return String[] Array der letzten Chatzeile n
*
**/
public Vector getChatLines(int anz) {
int size = 0;
Vector buffer=new Vector();
if ((size = lines.size()) != 0) {
if (anz >= size) {
for (int i = 0; i < size-1; i++)
buffer.add((String) lines.elementAt(i));
buffer
}
else {
for (int k = size - anz; k <= size -1; k++)
buffer.add((String) lines.elementAt(k));
buffer
}
return buffer;
}
else
return null;
}
/**
* Gibt den Namen des ChatRooms zurueck
zuruec
*
* @return name Name des ChatRooms
ChatRoom
*
**/
private String getName() {
return this.name;
}
/**
* Innere Klasse, welche die alten Chat-Lines
Chat-Line
* alle 10 Minuten aus dem Vector loescht .
*
* @version 1.0
1.
* @author Oliver Hilss
Hils
*
**/
private class Cleanup extends Thread {
public Cleanup() {
super();
super
}
public void run() {
while (true) {
try {
sleep(1000*60*10);
sleep
); // alle 10 Mins
}
catch (InterruptedException ie) {
ie.printStackTrace();
ie
}
synchronized (lines) {
if (lines.size() == time.size() && lines.size() > 0) {
try {
long difference = getDifference();
while (difference > 1000*60*10) {
lines.removeElementAt(0);
lines
time.removeElementAt(0);
time
System.out.println("Eine Chat-Zeile
System
geloescht....");
difference = getDifference();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private long getDifference() {
long result = 0;
if (time.size() > 0) {
result = System.currentTimeMillis() - ((Date)
time.firstElement()).getTime();
return result;
}
else return result;
}
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.ChatServer
mm.services.chat.ChatServer
public class ChatServer
implements Chat, java.lang.Runnable
Diese Klasse implementiert einen ChatServer, der die verschiedenen
ChatRooms managt anlegt und zerstoert.
Version:
0.1
Author:
Mirko und Oliver
ChatServer()
addChatListener(RemoteEventListener, MarshalledObject)
Registriert einen Client als RemoteEventListener beim Chatserver
cancel(Object)
Landlord Methoden
cancelAll(Object[])
chatRoomCreated(String)
createChatRoom(String)
Erzeugt einen Chat-Room
deleteChatRoom(String)
Loescht den angegebenen Chat-Room
getLastLines(int, String)
Gibt die letzten Chatzeilen zurueck.
getLine(String)
Gibt die letzte Chat-Line des angegebenen Chat-Rooms zurueck
insertLine(String, String)
Fuegt eine Chat-Line beim angegebenen Chat-Room ein
isAlive()
Hilfsmethoden
renew(Object, long)
renewAll(Object[], long[])
run()
Methoden fuer den Thread
ChatServer
public ChatServer() throws java.rmi.RemoteException
addChatListener
public net.jini.core.event.EventRegistration addChatListener(net.jini.core.event.RemoteEve
java.rmi.MarshalledObject handbackObject) throws
Registriert einen Client als RemoteEventListener beim Chatserver
Parameters:
addChatListener - Client uebergibt RemoteEventListener. An diesen
Listener wird der Event geschickt.
handbackObject - Object das vom Client uebergeben wird und
spaeter vom Listener des Clients mitgeschickt und ausgewertet
werden kann.
Returns:
EventRegistration
insertLine
public void insertLine(java.lang.String cr,
java.lang.String line)
Fuegt eine Chat-Line beim angegebenen Chat-Room ein
Parameters:
cr - Name des Chat-Rooms
line - Die Chat-Line fuer den Chat-Room
p - Der User von dem die Zeile stammt
Returns:
void
getLine
public java.lang.String getLine(java.lang.String cr)
Gibt die letzte Chat-Line des angegebenen Chat-Rooms zurueck
Parameters:
cr - Name des Chat-Rooms
Returns:
Die letzte Zeile des angegebenen ChatRooms
getLastLines
public java.lang.String[] getLastLines(int anz,
java.lang.String cr)
Gibt die letzten Chatzeilen zurueck. Anzahl der Zeilen kann
uebergeben werden.
Parameters:
anz - Anzahl der Zeilen
cr - Chatroom
Returns:
String[] Array mit den letzten Chatzeilen
createChatRoom
public void createChatRoom(java.lang.String cr)
Erzeugt einen Chat-Room
Parameters:
cr - Name des Chat-Rooms
Returns:
void
deleteChatRoom
public void deleteChatRoom(java.lang.String cr)
Loescht den angegebenen Chat-Room
Parameters:
cr - Name des Chat-Rooms
Returns:
void
chatRoomCreated
public boolean chatRoomCreated(java.lang.String cr)
cancel
public void cancel(java.lang.Object cookie)
Landlord Methoden
cancelAll
public void cancelAll(java.lang.Object cookie[])
renew
public long renew(java.lang.Object cookie,
long extension) throws net.jini.core.lease.LeaseDeniedException
renewAll
public com.sun.jini.lease.landlord.Landlord.RenewResults renewAll(java.lang.Object cookie[
long extension[])
run
public void run()
Methoden fuer den Thread
isAlive
public boolean isAlive()
Hilfsmethoden
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.chat;
import mm.services.chat.ChatRoom;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
import
import
import
import
import
import
import
com.sun.jini.lookup.JoinManager;
com.sun.jini.lease.LeaseRenewalManager;
com.sun.jini.lease.landlord.Landlord;
com.sun.jini.lease.landlord.LandlordLease.Factory;
com.sun.jini.lease.landlord.LandlordLease;
com.sun.jini.lease.landlord.LandlordLeaseFactory;
com.sun.jini.lease.landlord.LeasedResource;
import
import
import
import
import
import
import
net.jini.core.event.EventRegistration;
net.jini.core.event.RemoteEventListener;
net.jini.core.event.UnknownEventException;
net.jini.core.lease.Lease;
net.jini.core.lease.LeaseDeniedException;
net.jini.core.entry.Entry;
net.jini.lookup.entry.Name;
import
import
import
import
import
import
java.util.Hashtable;
java.util.Iterator;
java.util.List;
java.util.Map;
java.util.HashMap;
java.util.Vector;
/**
* Diese Klasse implementiert einen ChatServer, der di e
* verschiedenen ChatRooms managed, anlegt und zerstoert .
*
* @version 1.0
1.
* @author Oliver Hilss und Mirko Tochtermann
*
**/
public class ChatServer extends UnicastRemoteObject implements Chat,
Landlord, Runnable {
Hashtable chatRooms;
private static final long CHAT_ID = 0;
private long insertEventSequence = 0;
private final long maxLeaseDuration = 1000 * 60 * 120;
; //120 Minuten
private int leasesCreated = 0;
LandlordLeaseFactory leaseFactory;
HashMap activeLeases;
public ChatServer() throws RemoteException {
chatRooms = new Hashtable();
leaseFactory = new LandlordLease.Factory();
activeLeases = new HashMap();
}
/**
* Registriert einen Client als RemoteEventListener beim Chatserver
*
* @param addChatListener Client uebergibt RemoteEventListener. An diese n
* Listener wird der Event geschickt.
geschickt
* @param handbackObject Object das vom Client uebergeben wird und
un
spaeter vom
vo
* Listener des Clients mitgeschickt und ausgewertet werden kann .
* @return chatReg Objekt von EventRegistration
EventRegistratio
*
**/
public EventRegistration addChatListener(RemoteEventListener
chatListener,
MarshalledObject handbackObject) throws RemoteException,
LeaseDeniedException {
System.out.println ("Chat-Listener registrieren");
System
// Neues Lease-Cookie mit laufender Integer-Nummer erstellen
Object cookie = newLeaseCookie();
long leaseExpiration = maxLeaseDuration + now();
Lease eventLease = leaseFactory.newLease(cookie, this,
leaseExpiration);
// Event-Registration mit EventID, EventSource, Lease, EventSequenz
EventRegistration chatReg = new EventRegistration(CHAT_ID, this,
eventLease, insertEventSequence);
// Event-Daten in eventData ablegen
ChatEventData eventData = new ChatEventData(leaseExpiration,
chatListener, handbackObject);
// Event-Daten in der HashMap ablegen
// mit cookie als Key und eventData als Value
activeLeases.put(cookie, eventData);
activeLeases
printMessage("Registrierung beendet");
printMessage
return chatReg;
}
/**
* Informiert alle registrierten RemoteEventListener
* ueber einen aufgetretenen insertEvent.
insertEvent
*
* @param MarshalledObject Die Chat-Zeile, welche die Clients ausgebe n
sollen
solle
* @param String
String in dem der ChatRoom steht, der den Even t
ausloest
ausloes
* @return void
voi
*
**/
private void notifyChatListener(MarshalledObject chatLine, String cr) {
long now = now();
// Alle registrierten Listener in in einem Iterator ablegen...
Iterator listeners = activeLeases.values().iterator();
// ...und der Reihe nach ueber das Event informieren,
// falls die Lease noch nicht abgelaufen ist
while (listeners.hasNext()) {
ChatEventData eventInfo = (ChatEventData) listeners.next();
try {
printMessage("Send notify");
printMessage
if (eventInfo.getExpiration() > now) {
if
(eventInfo.getHandbackObject().get().toString().equals(cr)) {
printMessage("Marshalled
printMessage
Object: " +
eventInfo.getHandbackObject().get().toString());
eventInfo
eventInfo.notifyListener(CHAT_ID, this,
insertEventSequence, chatLine);
printMessage("Send notify for : " + cr);
printMessage
}
}
}
catch (UnknownEventException doesntKnow) {
printMessage("UnknownEventException" +
printMessage
doesntKnow.getMessage());
}
catch (RemoteException rmiProblem) {
printMessage("RemoteException" + rmiProblem.getMessage()
printMessage
);
}
catch (Exception e) {
e.printStackTrace();
e
}
}
}
/**
* Fuegt eine Chat-Line beim angegebenen Chat-Room ei n
*
* @param cr Name des Chat-Rooms
Chat-Room
* @param line Die Chat-Line fuer den Chat-Roo m
* @param p
Der User von dem die Zeile stammt
stamm
* @return void
voi
*
**/
public void insertLine(String cr, String line) {
insertEventSequence
insertEventSequence++;
ChatRoom c;
c
c=(ChatRoom) chatRooms.get(cr);
c
c.insertChatLine("> "+line);
printMessage
printMessage("Line eingefuegt");
try {
notifyChatListener(new MarshalledObject(line), cr);
notifyChatListener
}
catch (java.io.IOException ex) {
ex.printStackTrace();
ex
}
}
/**
* Gibt die letzte Chat-Line des angegebenen Chat-Rooms zuruec k
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return Die letzte Zeile des angegebenen ChatRoom s
*
**/
public String getLine(String cr) {
ChatRoom c;
c
c=(ChatRoom)chatRooms.get(cr);
if (c != null)
return c.getChatLine();
return "ChatRoom is empty or non-existent...";
}
/**
* Gibt die letzten Chatzeilen zurueck. Anzahl der Zeile n
* kann uebergeben werden.
werden
*
* @param anz
Anzahl der Zeilen
Zeile
* @param cr
Chatroo
Chatroom
* @return Vector
Vector mit den <anz> Chat-Zeilen
Chat-Zeile
*
**/
public Vector getLastLines(int anz, String cr) {
ChatRoom c=(ChatRoom)chatRooms.get(cr);
if (c != null)
return c.getChatLines(anz);
return
null;
null
}
/**
* Erzeugt einen Chat-Room
Chat-Roo
*
* @param cr Name des Chat-Rooms
Chat-Room
* @return void
voi
*
**/
public void createChatRoom(String cr) {
if (cr==null)
return;
return
if (!chatRooms.containsKey(cr)) {
System.out.println("Chatroom " + cr +" created");
System
chatRooms.put(cr,new ChatRoom(cr));
chatRooms
}
}
/**
* Loescht den angegebenen Chat-Room
Chat-Roo
*
* @param cr
Name des Chat-Rooms
Chat-Room
* @return void
voi
*
**/
public void deleteChatRoom(String cr) {
if (cr==null)
return;
return
Object obj = chatRooms.get(cr);
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.PageParameters
java.lang.Object
|
+----mm.services.chat.PageParameters
public class PageParameters
extends java.lang.Object
This is a tool class that simplifies the otherwise painful handling of POST
and GET parameters in the servlet API.
Version:
1.0
Author:
Stefan Zier
PageParameters(HttpServletRequest)
Constructor.
asHashtable()
Creates an Hashtable that coitains key/value pairs of the parameters.
count(String)
Counts how many times the parameter has been passed.
exists(String)
Checks whether a value exists or not.
getNumber(String)
Reads a value as a Number.
getNumber(String, int)
Reads a parameter as a Number.
getString(String)
Reads a parameter's value as a String.
getString(String, int)
Reads a parameters value as String.
PageParameters
public PageParameters(javax.servlet.http.HttpServletRequest request)
Constructor.
Parameters:
request - the HttpServletRequest that came with the service() call
of the servlet
exists
public boolean exists(java.lang.String name)
Checks whether a value exists or not.
Parameters:
name - the name of the value
getString
public java.lang.String getString(java.lang.String name,
int number)
Reads a parameters value as String. This is the more complex
method. It only has to be used when we expect multiple parameters with
the same name to come in.
Parameters:
name - the name of the parameter
number - the position of the parameter (0...n-1)
Returns:
the value of the parameter or an empty String if it doesn't exist
getString
public java.lang.String getString(java.lang.String name)
Reads a parameter's value as a String.
Parameters:
name - the name of the parameter
Returns:
the parameter's value as a String of an empty String if the
parameter does not exist
getNumber
public int getNumber(java.lang.String name,
int number)
Reads a parameter as a Number. This is the more complex method.
It only has to be used when we expect multiple parameters with the same
name to come in.
Parameters:
name - the name of the parameter
number - the position of the parameter (0..n-1)
Returns:
the paramters value as a int or -1 if the parameter does not exist
getNumber
public int getNumber(java.lang.String name)
Reads a value as a Number.
Parameters:
name - the name of the parameter
Returns:
the value as a String or -1 if the parameter does not exist
count
public int count(java.lang.String name)
Counts how many times the parameter has been passed.
Parameters:
name - the name of the parameter
Returns:
the number of occurences
asHashtable
public java.util.Hashtable asHashtable()
Creates an Hashtable that coitains key/value pairs of the
parameters.
Returns:
the Hashtable with all values
All Packages
Class Hierarchy
This Package
Previous
Next
Index
if (obj != null) {
System.out.println("Chatroom " + cr +" removed");
System
chatRooms.remove(cr);
chatRooms
}
}
/**
* Erzeugt einen Chat-Roo
Chat-Room
*
* @param cr
Name des Chat-Rooms
Chat-Room
* @return void
voi
*
**/
public boolean chatRoomCreated(String cr) {
if (cr == null)
return false;
if (chatRooms.containsKey(cr))
))
return true;
return false;
;
}
/**
* Löscht ein Lease aus unserer HashMap.
*
* @param cookie
Cookie Object unseres Leases
Lease
* @return void
voi
*
**/
public void cancel(java.lang.Object cookie) {
printMessage( "Cancel wurde aufgerufen" );
printMessage
if ( !activeLeases.containsKey( cookie ) )
return;
return
synchronized(activeLeases) {
activeLeases.remove( cookie );
activeLeases
}
}
/**
* Löscht alle Leases aus unserer HashMap
HashMa
*
* @param cookie
Array aus unseren Cookies
Cookie
* @return void
voi
*
**/
public void cancelAll(java.lang.Object[] cookie) {
for ( int k = 0; k < cookie.length; k++ )
cancel(cookie[k]);
cancel
}
/**
* Erneuert die Lease-Time eines Objects.
Objects
*
* @param cookie
Cookie zu unserem Lease
Leas
* @param extension
Zeitdauer um die der Lease verlängert wird
wir
* @return
long
Neue Zeitdauer des Leaes
Leae
*
**/
public long renew(Object cookie,long extension) throws
LeaseDeniedException {
printMessage( "Renew called " + extension );
printMessage
synchronized (activeLeases) {
if (!activeLeases.containsKey(cookie))
throw new LeaseDeniedException("Requested resourse does not
exist");
long newDuration = Math.min(extension, maxLeaseDuration);
ChatEventData eventLease = (ChatEventData)
activeLeases.get(cookie);
eventLease.setDuration(newDuration);
eventLease
return newDuration;
}
}
/**
* Erneuert alle Lease-Times unserer Objekte.
Objekte
*
* @param cookie
Cookie-Array zu unserem Leases
Lease
* @param extension
Array aus der Zeitdauer um die jeder Leas e
verlängert wird
wir
* @return
long
Neue Zeitdauer des Leaes
Leae
*
**/
public Landlord.RenewResults renewAll(java.lang.Object[] cookie,long[]
extension) {
long renewalGranted[] = new long[ cookie.length ];
Exception renewalDenied[] = new Exception[ cookie.length ];
for ( int k = 0; k < cookie.length; k++ ) {
try {
renewalGranted[k] = renew(cookie[k], extension[k]);
renewalGranted
renewalDenied[k] = null;
renewalDenied
}
catch (LeaseDeniedException deny ) {
renewalGranted[k] = -1;
renewalGranted
renewalDenied[k] = deny;
renewalDenied
}
}
return new Landlord.RenewResults(renewalGranted, renewalDenied );
}
/**
* Run-Methode fuer den Thread, welcher nach der Haelft e
* von maxLeaseDuration alle Leases checkt
check
*
*/
public void run()
run
{
try {
while (true) {
Thread.sleep( maxLeaseDuration/2 );
Thread
printMessage ("CheckAllLeases");
checkAllLeases();
checkAllLeases
}
}
catch (InterruptedException ie) {
ie.printStackTrace();
ie
}
}
/**
* Dient zum Check aller vergebenen Leases.
Leases
* Die HashMap "activeLeases" wird dabei synchronisiert.
synchronisiert
*
* @return void
voi
*
**/
private void checkAllLeases() {
synchronized ( activeLeases ) {
Iterator counterKeys = activeLeases.keySet().iterator();
while (counterKeys.hasNext()) {
Object key = counterKeys.next();
if (hasLeaseExpired(key)) {
counterKeys.remove();
counterKeys
printMessage( "lease expired " + key );
printMessage
}
}
}
}
/**
* Dient zum Test, ob eine Lease bereits abgelaufen is t
*
* @param cookie Cookie, welches als Schluessel fuer die HashMa p
"activeLeases" dient
dien
* @return boolean true, falls Lease abgelaufen; false, falls Lease noc h
besteht
besteh
*
**/
private boolean hasLeaseExpired(Object cookie) {
ChatEventData aCounter = (ChatEventData) activeLeases.get(cookie);
long expiration = aCounter.getExpiration();
printMessage("lease check " + cookie
printMessage
(expiration - now()) );
if ( now() >= expiration )
return true;
else
return false;
}
+ "
duration " +
// Hilfsmethoden
/**
* Diese Methode dient dazu den Zustand des Servlet s
* zu checken (AliveCheck).
(AliveCheck)
*
* @return boolean
Gibt true zurück wenn das Servlet noch reagier t
*
**/
public boolean isAlive() {
return true;
}
/**
* Erzeugt ein neues Lease-Cooki
Lease-Cookie
*
* @return
Integer Unser neues Lease-Cookie
Lease-Cooki
*
**/
private Integer newLeaseCookie() {
return new Integer(leasesCreated++);
}
/**
* Stellt die momentane Zeit in Millisekunden fes t
*
* @return long
Die momentane Zeit in Millisekunden
Millisekunde
*
**/
private long now() {
return System.currentTimeMillis();
}
/**
* Schreibt einen String nach Standard Ou
Out
*
* @param message
Der Message-String der nach Standard Ou
Out
geschrieben werden soll
sol
*
**/
private void printMessage(String message) {
System.out.println(toString()+ " " + message);
System
}
}
package mm.services.chat;
// Servlet API imports
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpUtils;
import javax.servlet.ServletInputStream;
// Core Java imports
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.IOException;
/**
* This is a tool class that simplifies the otherwise painful handling o f
POST and GET parameters
parameter
* in the servlet API.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class PageParameters
{
// this is where we store the parsed values
protected Hashtable parsed_values = null;
// we implement "lazy parsing" meaning we parse on demand
protected boolean parsed = false;
// this is where we store the servlet request - needed for lazy parsing
protected HttpServletRequest request = null;
/**
* Constructor.
Constructor
*
* @param request the HttpServletRequest that came with the service( )
call of the servlet
servle
*/
public PageParameters(HttpServletRequest request)
{
// for now we only store the HttpServletRequest
this.request = request;
this
}
/**
* This method does the actual parsing - when we need it. +
*/
protected void parse()
{
// get the querystring and parse it
String querystring = request.getQueryString();
Hashtable qs_parsed = null;
if(querystring != null)
if
qs_parsed = HttpUtils.parseQueryString(querystring);
// get the POSTed data and parse it
ServletInputStream data = null;
try
{
data = request.getInputStream();
}
catch(IOException ioe)
catch
{
}
Hashtable post_parsed = null;
if
if(data
!= null && (request.getContentLength() != -1))
post_parsed = HttpUtils.parsePostData(request.getContentLength(),
data);
// now try to merge both
if(qs_parsed == null && post_parsed == null)
if
parsed_values = new Hashtable();
else if(qs_parsed == null && post_parsed != null)
parsed_values = post_parsed;
else if(qs_parsed != null && post_parsed == null)
parsed_values = qs_parsed;
else
{
// well, now we really have to merge. Shouldn't be much of a
Problem though.
Enumeration enum = qs_parsed.keys();
while(enum.hasMoreElements())
while
{
String key = (String)enum.nextElement();
if(post_parsed.get(key) == null)
if
post_parsed.put(key, qs_parsed.get(key));
post_parsed
else
{
// jeeze. The value existed already in the posted data,
let's merge both arrays
String[] qs_values = (String[]) qs_parsed.get(key);
String
String[] post_values = (String[]) post_parsed.get(key);
String
// create our new array
String[] merged_values = new String[qs_values.length +
String
post_values.length];
// insert the query string values
for(int i=0; i < qs_values.length; i++)
for
merged_values[i] = qs_values[i];
merged_values
// insert the post string values
for(int i=0; i < post_values.length; i++)
for
merged_values[i + qs_values.length] = post_values[i];
merged_values
// insert our new array
post_parsed.put(key, merged_values);
post_parsed
}
}
parsed_values = post_parsed;
}
// make sure we don't have to parse again
parsed = true;
}
/**
* Checks whether a value exists or not .
*
* @param name the name of the valu e
*/
public boolean exists(String name)
{
// lazy parsing
if(!parsed)
if
parse();
parse
// get the string array
String[] values = (String[]) parsed_values.get(name);
String
if(values == null)
if
return false;
if(values.length == 0)
if
return false;
if(values[0] == null)
if
return false;
return true;
}
/**
* Reads a parameters value as String. This is the more complex method .
It only has to be used
use
* when we expect multiple parameters with the same name to come in .
*
* @param name the name of the paramete r
* @param number the position of the parameter (0...n-1 )
* @return the value of the parameter or an empty String if it doesn' t
exist
exis
*/
public String getString(String name, int number)
{
// lazy parsing
if(!parsed)
if
parse();
parse
// try to read something
String[] values = (String[]) parsed_values.get(name);
String
if(
if
(
values == null)
return new String();
String value = null;
// try to read the String
try
{
value = values[number];
];
}
catch(ArrayIndexOutOfBoundsException aioobe)
catch
{
// in case the number is not in the arrays range return an empty
String
return new String();
}
// ok, let's see if we've got something
if(value == null)
if
return new String();
// yup, return it
return value;
}
/**
* Reads a parameter's value as a String .
*
* @param name the name of the paramete r
* @return the parameter's value as a String of an empty String if th e
parameter does not exist
exis
*/
public String getString(String name)
{
return getString(name, 0);
}
/**
* Reads a parameter as a Number. This is the more complex method. I t
only has to be used
use
* when we expect multiple parameters with the same name to come in .
*
* @param name the name of the paramete r
* @param number the position of the parameter (0..n-1 )
* @return the paramters value as a int or -1 if the parameter does no t
exist
exis
*/
public int getNumber(String name, int number)
{
// lazy parsing
if(!parsed)
if
parse();
parse
// try to read something
String[] values = (String[]) parsed_values.get(name);
String
if(
if
(
values == null)
return -1;
String value = null;
// try to read the String
try
{
value = values[number];
];
}
catch(ArrayIndexOutOfBoundsException aioobe)
catch
{
// in case the number is not in the arrays range return -1
return -1;
}
// ok, let's see if we've got something
if(value == null)
if
return -1;
int num_value = -1;
// yup, convert to integer return it
try
{
num_value = Integer.parseInt(value.trim());
}
catch(NumberFormatException nfe)
catch
{
return -1;
}
return num_value;
}
/**
* Reads a value as a Number.
*
* @param name the name of the parameter
* @return the value as a String or -1 if the parameter does not exis t
*/
public int getNumber(String name)
{
return getNumber(name, 0);
}
/**
* Counts how many times the parameter has been passed .
*
* @param name the name of the paramete r
* @return the number of occurences
occurence
*/
public int count(String name)
{
// lazy parsing
if(!parsed)
if
parse();
parse
String[] values = (String[]) parsed_values.get(name);
String
if(values == null)
if
return 0;
return values.length;
}
/**
* Creates an Hashtable that coitains key/value pairs of the
* parameters.
parameters
*
* @return the Hashtable with all value s
*/
public Hashtable asHashtable()
{
// the result
Hashtable result = new Hashtable();
// lazy parsing
if(!parsed)
if
parse();
parse
// write the first of all values into the new Hashtable
Enumeration enum = parsed_values.keys();
while(enum.hasMoreElements())
while
{
String key = (String) enum.nextElement();
String
String[]
values = (String[]) parsed_values.get(key);
if(values != null)
if
{
String value = values[0];
if(value != null)
if
result.put(key, value);
result
}
}
// return the hashtable
return result;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.chat.SessionManager
java.lang.Object
|
+----mm.webserver.jsp.JspSuperClass
|
+----mm.services.chat.SessionManager
public class SessionManager
extends mm.webserver.jsp.JspSuperClass
Das SessionManager-Servlet dient dazu, die Sessions der einzelnen Clients
zu managen. Es wird nur fuer noch nicht angemeldete Clients eine neue
Session erzeugt. Die Default-Werte fuer NickName ist "guest" und fuer
Farbe "schwarz"
Version:
1.0
Author:
Mirko Tochtermann
SessionManager()
_jspService(HttpServletRequest, HttpServletResponse)
In _jspService() wird gegebenenfalls eine neue HttpSession mit den
entsprechenden Werten von "NickName" bzw.
jspInit()
SessionManager
public SessionManager()
jspInit
public void jspInit()
Overrides:
jspInit in class mm.webserver.jsp.JspSuperClass
_jspService
public void _jspService(javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse res)
In _jspService() wird gegebenenfalls eine neue HttpSession mit den
entsprechenden Werten von "NickName" bzw. "Farbe" erzeugt.
Parameters:
req - Das HttpServletRequest-Objekt
res - Das HttpServletResponse-Objekt
Returns:
void
Overrides:
_jspService in class mm.webserver.jsp.JspSuperClass
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package
mm.services.chat;
mm
import java.util.Hashtable;
import java.util.Vector;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStream;
import
import
import
import
import
import
import
import
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;
javax.servlet.ServletException;
javax.servlet.ServletContext;
javax.servlet.ServletInputStream;
javax.servlet.http.HttpUtils;
javax.servlet.RequestDispatcher;
import mm.webserver.jsp.JspSuperClass;
import mm.jini.ServiceController;
/**
* Das SessionManager-Servlet dient dazu, die Sessions der einzelne n
* Clients zu managen.
* Es wird nur fuer noch nicht angemeldete Clients eine neue Sessio n
erzeugt.
erzeugt
* Die Default-Werte fuer NickName ist "guest" und fuer Farbe "schwarz "
*
* @version 1.0
1.
* @author Mirko Tochtermann
Tochterman
*
**/
public class SessionManager extends JspSuperClass {
public void jspInit() {
}
/**
* In _jspService() wird gegebenenfalls eine neue HttpSessio n
* mit den entsprechenden Werten von "NickName" bzw. "Farbe" erzeugt .
*
* @param req Das HttpServletRequest-Objekt
HttpServletRequest-Objek
* @param res Das HttpServletResponse-Objekt
HttpServletResponse-Objek
* @return void
voi
*
**/
public void _jspService(HttpServletRequest req, HttpServletResponse res)
{
PrintWriter out = null;
String chatName = null;
String chatFarbe = null;
HttpSession oursession = req.getSession(true);
);
PageParameters params = new PageParameters(req);
if (oursession.isNew()) {
chatName=new String("guest");
chatName
chatFarbe=new String("schwarz");
chatFarbe
}
else {
chatName = params.getString("NickName");
chatFarbe = params.getString("Farbe");
}
try {
out = res.getWriter();
}
catch (IOException ioe) {
ioe.printStackTrace();
ioe
}
oursession.putValue("NickName",chatName);
oursession
oursession.putValue("Farbe",chatFarbe);
oursession
out.println("<!DOCTYPE HTML PUBLIC \"out
-//W3C//DTD HTML 4.0
Transitional//EN\">");
out.println("<html> <head><title>MM Chat Options</title></head>");
out
out.println("<body><form
out
action=\"http://motion.ghb.fh-furtwangen.de:8001/servlet/Sessionmanager\"
method=\"POST\">");
out.println("Nickname: <br>");
out
out.println("<input type=\"Text\" name=\"NickName\"
out
value=\""+chatName + "\" size=\"20\" maxlength=\"30\"
title=\"Nickname\"><br>");
out.println("<input type=\"Radio\" name=\"Farbe\" checked
out
value=\"rot\" title=\"Farbe\"> <font color=\"#FF0000\"> Rot <br>");
out.println("<input type=\"Radio\" name=\"Farbe\" value=\"blau\"
out
title=\"Farbe\"><font color=\"#0000FF\"> Blau <br>");
out.println("<input type=\"Radio\" name=\"Farbe\" value=\"gruen\"
out
title=\"Farbe\"><font color=\"#00FF00\"> Gruen <br>");
out.println("<input type=\"Radio\" name=\"Farbe\" value=\"schwarz\"
out
title=\"Farbe\"><font color=\"#000000\"> Schwarz <br>");
out.println("<input type=\"Submit\" name=\"submit\"
out
title=\"Abschicken\">");
out.println("</form></body></html>");
out
out.flush();
out
();
}
}
c.) mm.services.files
Dieses Package enthält Klassen des Fileserver-Dienstes.
Klasse
FileInfo
FileServer
FileServerImpl
RegisterFileServer
Bedeutung
Speichert Informationen zu einer Datei
(Name, Datum, etc.)
Das Remote Interface des Fileservers
Implementation des Fileservers
Hilfsklasse, die einen Fileserver instantiiert
und beim Lookup Service anmeldet
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.files.FileInfo
java.lang.Object
|
+----mm.services.files.FileInfo
public class FileInfo
extends java.lang.Object
implements java.io.Serializable
Diese Klasse repräsentiert eine Datei die in einem Place gespeichert
werden kann. Sie kapselt Zusatzinformationen wie Name, Datum etc.,
jedoch nicht den Inhalt.
Version:
1.0
Author:
Stefan Zier
FileInfo(String, long, Date, String)
Erstellt ein FileInfo-Objekt.
getCreated()
Accessor für
getLength()
Accessor für
getName()
Accessor für
getUploader()
Accessor für
created.
length.
name.
uploader.
FileInfo
public FileInfo(java.lang.String name,
long length,
java.util.Date created,
java.lang.String uploader)
Erstellt ein FileInfo-Objekt.
Parameters:
name - der Name der Datei
length - die Lände der Datei
created - das Datum an dem die Datei hochgeladen/erstellt wurde
getName
public java.lang.String getName()
Accessor für name. Liefert den Namen der Datei zurück.
Returns:
die Länge der Datei
getLength
public long getLength()
Accessor für length. Liefert die Länge der Datei zurück.
Returns:
die Länge der Datei.
getCreated
public java.util.Date getCreated()
Accessor für created. Liefert das Datum zurück an dem die Datei
angelegt wurde.
Returns:
das Datum an dem die Datei angelegt wurde.
getUploader
public java.lang.String getUploader()
Accessor für uploader. Liefert den Namen des Benutzers der die
Datei hochgeladen hat.
Returns:
den Namen des Benutzers der die Datei hochgeladen hat.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.files;
import java.util.Date;
import java.io.Serializable;
/**
* Diese Klasse repräsentiert eine Datei die in einem Place gespeicher t
werden
werde
* kann. Sie kapselt Zusatzinformationen wie Name, Datum etc., jedoch nich t
den
* Inhalt.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class FileInfo implements Serializable
{
private String name = null;
private long length = -1;
private Date created = null;
private String uploader = null;
/**
* Erstellt ein FileInfo-Objekt.
* @param name der Name der Datei
Date
* @param length die Lände der Date i
* @param created das Datum an dem die Datei hochgeladen/erstellt wurd e
*/
public FileInfo(String name, long length, Date created, String uploader)
{
this.name = name;
this
this.length = length;
this
this.created = created;
this
this.uploader = uploader;
this
}
/**
* Accessor für name. Liefert den Namen der Datei zurück .
*
* @return die Länge der Datei
Date
*/
public String getName()
{
return name;
}
/**
* Accessor für length. Liefert die Länge der Datei zurück .
*
* @return die Länge der Datei.
Datei
*/
public long getLength()
{
return length;
}
/**
* Accessor für created. Liefert das Datum zurück an dem die Date i
angelegt
angeleg
* wurde.
wurde
*
* @return das Datum an dem die Datei angelegt wurde .
*/
public Date getCreated()
{
return created;
}
/**
* Accessor für uploader. Liefert den Namen des Benutzers der die Date i
hochgeladen hat.
hat
*
* @return den Namen des Benutzers der die Datei hochgeladen hat .
*/
public String getUploader()
{
return uploader;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface mm.services.files.FileServer
public interface FileServer
extends java.rmi.Remote, AliveCheckable
Dies ist das Interface zum Fileserver der Anwendung. Er verwaltet alle
Dateien in sogenannten file places, also in Ablagen. Dabei besteht keine
Möglichkeit, diese Ablagen zu strukturieren, z.B. durch Unterverzeichnisse
o.Ä. Places werden als Strings identifiziert.
Version:
1.0
Author:
Stefan Zier
deletePlace(String)
Diese Methode löscht einen Place samt allen darin enthaltenen
Dateien.
getFile(String, String)
Diese Methode liefert den Inhalt einer Datei zurück.
listFiles(String)
Diese Methode listet all Dateien in einem Place auf.
putFile(String, String, String, byte[])
Speichert eine Datei ein einem place.
putFile
public void putFile(java.lang.String place,
java.lang.String uploader,
java.lang.String name,
byte content[]) throws java.rmi.RemoteException
Speichert eine Datei ein einem place. Existiert bereits eine Datei mit
dem gleichen Namen so wird sie überschrieben
Parameters:
place - Der identifier für den Place. Existiert der Place nicht bereits
so wird er erstellt.
uploader - Der Mitspieler der die Datei hochgeladen hat
name - Der Name der Datei
content - Der Inhalt der Datei
listFiles
public java.util.Vector listFiles(java.lang.String place) throws java.rmi.RemoteException
Diese Methode listet all Dateien in einem Place auf. Dabei gibt sie
einen sortierten Vector zurück, der Einträge der Klasse FileInfo enthält.
Parameters:
place - der Place der gelistet werden soll
Returns:
einen Vector mit FileInfo records
getFile
public byte[] getFile(java.lang.String place,
java.lang.String name) throws java.rmi.RemoteException
Diese Methode liefert den Inhalt einer Datei zurück.
Parameters:
place - der Place von dem die Datei heruntergeladen werden soll
name - der Name der Datei die heruntergeladen werden soll
Returns:
der Inhalt der Datei
deletePlace
public void deletePlace(java.lang.String place) throws java.rmi.RemoteException
Diese Methode löscht einen Place samt allen darin enthaltenen
Dateien.
Parameters:
place - der Place der gelöscht werden soll.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.files;
import java.util.Vector;
import java.rmi.Remote;
import java.rmi.RemoteException;
import mm.tools.AliveCheckable;
/**
* Dies ist das Interface zum Fileserver der Anwendung. Er verwaltet all e
Dateien
Dateie
* in sogenannten file places, also in Ablagen. Dabei besteht kein e
Möglichkeit,
Möglichkeit
* diese Ablagen zu strukturieren, z.B. durch Unterverzeichnisse o.Ä .
Places werden
werde
* als Strings identifiziert.
identifiziert
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public interface FileServer extends Remote, AliveCheckable
{
/**
* Speichert eine Datei ein einem place. Existiert bereits eine Date i
mit dem
de
* gleichen Namen so wird sie überschriebe n
*
* @param place Der identifier für den Place. Existiert der Place nich t
bereits
bereit
*
so wird er erstellt .
* @param uploader Der Mitspieler der die Datei hochgeladen ha t
* @param name Der Name der Datei
Date
* @param content Der Inhalt der Date i
*/
public void putFile(String place, String uploader, String name, byte[]
content)
throws RemoteException;
/**
* Diese Methode listet all Dateien in einem Place auf. Dabei gibt si e
einen
* sortierten Vector zurück, der Einträge der Klasse FileInfo enthält.
*
* @param place der Place der gelistet werden sol l
* @return einen Vector mit FileInfo record s
*/
public Vector listFiles(String place)
throws RemoteException;
/**
* Diese Methode liefert den Inhalt einer Datei zurück .
*
* @param place der Place von dem die Datei heruntergeladen werden sol l
* @param name der Name der Datei die heruntergeladen werden sol l
* @return der Inhalt der Datei
Date
*/
public byte[] getFile(String place, String name)
throws RemoteException;
/**
* Diese Methode löscht einen Place samt allen darin enthaltene n
Dateien.
Dateien
*
* @param place der Place der gelöscht werden soll .
*/
public void deletePlace(String place)
throws RemoteException;
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.files.FileServerImpl
mm.services.files.FileServerImpl
public class FileServerImpl
implements FileServer
Diese Klasse implementiert den Fileserver. Sie liest die Konfigurationsdatei
fileserver.properties.
Version:
1.0
Author:
Stefan Zier
FileServerImpl()
Konstruktur.
deletePlace(String)
Diese Metode löscht einen Place samt allen darin enthaltenen Dateien.
getFile(String, String)
Diese Methode liefert den Inhalt einer Datei zurück.
isAlive()
Gibt true zurück wenn alles mit dem FileServer in Ordnung ist.
listFiles(String)
Diese Methode listet all Dateien in einem Place auf.
putFile(String, String, String, byte[])
Speichert eine Datei ein einem place.
serviceIDNotify(ServiceID)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
FileServerImpl
public FileServerImpl() throws java.rmi.RemoteException, java.sql.SQLException, java.io.IO
Konstruktur. Liest die Konfigurationsdatei und baut den DatenbankVerbindungs-Pool auf.
Throws:
java.sql.SQLException - Wenn was mit den
Datenbankverbindungen schiefgeht.
java.io.IOException - Wenn was mit dem Configfile schiefgeht.
java.lang.ClassNotFoundException - Wenn das mit dem
Connection Pool Manager schiefgeht.
java.lang.InstantiationException - Wenn das mit dem Connection
Pool Manager schiefgeht.
java.lang.IllegalAccessException - Wenn das mit dem Connection
Pool Manager schiefgeht.
putFile
public void putFile(java.lang.String place,
java.lang.String uploader,
java.lang.String name,
byte content[]) throws java.rmi.RemoteException
Speichert eine Datei ein einem place. Existiert bereits eine Datei mit
dem gleichen Namen so wird sie überschrieben
Parameters:
place - Der identifier für den Place. Existiert der Place nicht bereits
so wird er erstellt.
uploader - Der Mitspieler der die Datei hochgeladen hat
name - Der Name der Datei
content - Der Inhalt der Datei
listFiles
public java.util.Vector listFiles(java.lang.String place) throws java.rmi.RemoteException
Diese Methode listet all Dateien in einem Place auf. Dabei gibt sie
einen sortierten Vector zurück, der Einträge der Klasse FileInfo enthält.
Parameters:
place - der Place der gelistet werden soll
Returns:
einen Vector mit FileInfo records
getFile
public byte[] getFile(java.lang.String place,
java.lang.String name) throws java.rmi.RemoteException
Diese Methode liefert den Inhalt einer Datei zurück.
Parameters:
place - der Place von dem
name - der Name der Datei
die Datei heruntergeladen werden soll
die heruntergeladen werden soll
Returns:
der Inhalt der Datei oder null wenn die Datei nicht gelesen
werden konnte
deletePlace
public void deletePlace(java.lang.String place) throws java.rmi.RemoteException
Diese Metode löscht einen Place samt allen darin enthaltenen
Dateien.
Parameters:
place - der Place der gelöscht werden soll.
serviceIDNotify
public void serviceIDNotify(net.jini.core.lookup.ServiceID service_id)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
Parameters:
service_id - Service ID
isAlive
public boolean isAlive() throws java.rmi.RemoteException
Gibt true zurück wenn alles mit dem FileServer in Ordnung ist.
Returns:
true wenn alles mit dem FileServer in Ordnung ist.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.files;
// Java core imports
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.util.Vector;
import java.util.Date;
// Jini extension imports
import com.sun.jini.lookup.ServiceIDListener;
import net.jini.core.lookup.ServiceID;
// Database connection imports
import com.bitmechanic.sql.ConnectionPoolManager;
import com.bitmechanic.sql.ConnectionPool;
// MM Project imports
import mm.tools.ConfigFile;
import mm.tools.Static;
/**
* Diese Klasse implementiert den Fileserver. Sie liest di e
Konfigurationsdatei
* fileserver.properties.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class FileServerImpl extends UnicastRemoteObject implements
FileServer, ServiceIDListener
{
// database connections
private ConnectionPoolManager cpm = null;
private ConnectionPool pool = null;
// file locations
private String basepath = null;
/**
* Konstruktur. Liest die Konfigurationsdatei und baut de n
Datenbank-Verbindungs-Pool
* auf.
auf
*
* @exception SQLException Wenn was mit den Datenbankverbindunge n
schiefgeht.
schiefgeht
* @exception IOException Wenn was mit dem Configfile schiefgeht .
* @exception ClassNotFoundException Wenn das mit dem Connection Poo l
Manager schiefgeht.
schiefgeht
* @exception InstantiationException Wenn das mit dem Connection Poo l
Manager schiefgeht.
schiefgeht
* @exception IllegalAccessException Wenn das mit dem Connection Poo l
Manager schiefgeht.
schiefgeht
*/
public FileServerImpl()
throws RemoteException, SQLException, IOException,
ClassNotFoundException,
InstantiationException, IllegalAccessException
InstantiationException
{
super();
super
ConfigFile configfile = new
ConfigFile("f:\\mm\\services\\files\\fileserver.properties");
// create a connection pool manager
cpm = new ConnectionPoolManager(120);
// get
String
String
String
url, username and password from the configuration file
url = configfile.get("fileserver.database.URL");
username = configfile.get("fileserver.database.username");
password = configfile.get("fileserver.database.password");
basepath = configfile.get("fileserver.basepath");
if
if(basepath
== null || basepath.equals(""))
{
throw new IllegalArgumentException("mm: no
}
if(url == null || url.equals(""))
if
{
throw new IllegalArgumentException("mm: no
}
if(username == null || username.equals(""))
if
{
throw new IllegalArgumentException("mm: no
}
if(password == null || password.equals(""))
if
{
throw new IllegalArgumentException("mm: no
given");
}
base path given");
database URL given");
database login given");
database password
// add the alias for "our" database
cpm.addAlias("fileserver", "org.gjt.mm.mysql.Driver", url, username,
cpm
password, 120, 300, 120);
pool = cpm.getPool("fileserver");
}
/**
* Speichert eine Datei ein einem place. Existiert bereits eine Date i
mit dem
de
* gleichen Namen so wird sie überschriebe n
*
* @param place Der identifier für den Place. Existiert der Place nich t
bereits
bereit
*
so wird er erstellt .
* @param uploader Der Mitspieler der die Datei hochgeladen ha t
* @param name Der Name der Datei
Date
* @param content Der Inhalt der Date i
*/
public void putFile(String place, String uploader, String name, byte[]
content)
throws RemoteException
{
// checken ob die Parameter korrekt sind
if(Static.empty(place))
if
throw new IllegalArgumentException("mm: place was empty in
putFile()");
if(Static.empty(uploader))
if
throw new IllegalArgumentException("mm: uploader was empty in
putFile()");
if(Static.empty(name))
if
throw new IllegalArgumentException("mm: name was empty in
putFile()");
if(content == null)
if
throw new IllegalArgumentException("mm: content was null in
putFile()");
// checken ob der place existiert und ein Verzeichnis ist
File directory = new File(basepath + "/" + place);
if
if(!directory.exists())
{
// create the place
if(!directory.mkdir())
if
throw new IllegalArgumentException("mm: the place could not be
created");
}
else
{
if(!directory.isDirectory())
if
throw new IllegalArgumentException("mm: the place is not a
directory!");
}
// Jetzt können wir sicher sein ein existierendes Verzeichnis zu
haben.
// ist die Datei schon da?
File file = new File(basepath + "/" + place + "/" + name);
// ist die Datei schon da, dann löschen
if(file.exists())
if
file.delete();
file
try
{
// outputstream öffnen
FileOutputStream out = new FileOutputStream(file);
// inhalt in die datei schreiben
out.write(content);
out
// stream schliessen
out.close();
out
}
catch(IOException ioe)
catch
{
throw new RemoteException("mm: the file could not be written",
ioe);
}
// ok, die Datei ist auf der Platte, jetzt müssen wir noch den
Uploader
// in die Datenbank schreiben
try
{
// ggf. vorhandene alte Einträge entfernen
String query = "DELETE FROM files WHERE place=" +
Static.sqlString(place) + " AND name=" + Static.sqlString(name);
// datenbank-verbindung aus dem pool holen
Connection conn = pool.getConnection();
Statement sDeleteFile = conn.createStatement();
sDeleteFile.execute(query);
sDeleteFile
sDeleteFile.close();
sDeleteFile
// neuen eintrag einfügen
query = "INSERT INTO files (place, name, uploader) values(";
query += Static.sqlString(place);
query += ", ";
query += Static.sqlString(name);
query += ", ";
query += Static.sqlString(uploader);
query += ")";
Statement sInsertFile = conn.createStatement();
sInsertFile.execute(query);
sInsertFile
sInsertFile.close();
sInsertFile
// datenbank-verbindung in den pool zurückstellen
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: the file could not be written to
the database", sql);
}
}
/**
* Diese Methode listet all Dateien in einem Place auf. Dabei gibt si e
einen
* sortierten Vector zurück, der Einträge der Klasse FileInfo enthält.
*
* @param place der Place der gelistet werden sol l
* @return einen Vector mit FileInfo record s
*/
public Vector listFiles(String place)
throws RemoteException
{
// checken ob die Parameter korrekt sind
if(Static.empty(place))
if
throw new IllegalArgumentException("mm: place was empty in
putFile()");
Vector out = new Vector();
// checken ob der place existiert und ein Verzeichnis ist
File directory = new File(basepath + "/" + place);
// wenn es den Place nicht gibt den leeren Vector zurückgeben
if(!directory.exists())
if
return out;
// filelist holen
String[] files = directory.list();
String
// filelist sortieren
Static.sortStrings(files);
Static
// durch die filelist gehen
for(int i=0; i<files.length;i++)
for
{
File file = new File(directory.getPath() + "/" + files[i]);
if(file.exists() && !file.isDirectory())
if
{
// uploader aus der Datenbank lesen
String uploader = null;
try
{
String query = "SELECT uploader FROM files WHERE place=";
query += Static.sqlString(place);
query += " AND name=";
query += Static.sqlString(files[i]);
// connection aus dem pool holen
Connection conn = pool.getConnection();
Statement sGetFile = conn.createStatement();
ResultSet rsGetFile = sGetFile.executeQuery(query);
// wenn records gelesen wurden
if(rsGetFile.next())
if
{
uploader = rsGetFile.getString("uploader");
}
sGetFile.close();
sGetFile
// connection in den pool zurückstellen
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: uploader konnte nicht aus der
Datenbank gelesen werden.", sql);
}
FileInfo fi = new FileInfo(files[i], file.length(), new
Date(file.lastModified()), uploader);
out.addElement(fi);
out
}
}
return out;
}
/**
* Diese Methode liefert den Inhalt einer Datei zurück .
*
* @param place der Place von dem die Datei heruntergeladen werden sol l
* @param name der Name der Datei die heruntergeladen werden sol l
* @return der Inhalt der Datei oder null wenn die Datei nicht gelese n
werden konnte
konnt
*/
public byte[] getFile(String place, String name)
throws RemoteException
{
File file = new File(basepath + "/" + place + "/" + name);
// prüfen ob die Datei existiert und kein Verzeichnis ist
if(!file.exists() || file.isDirectory())
if
return null;
byte[] result = null;
byte
try
{
// datei öffnen
FileInputStream in = new FileInputStream(file);
// einen puffer in grösse der Datei anlegen
int size = (int) file.length();
result = new byte[size];
// Datei in den Puffer lesen
in.read(result);
in
// datei schliessen
in.close();
in
}
catch(IOException ioe)
catch
{
throw new RemoteException("mm: could not read the file from disk" ,
ioe);
}
// den Puffer zurückgeben
return result;
}
/**
* Private Methode, die eine Datei/ein Verzeichnis rekursiv löscht .
*
* @param file die Datei/das Verzeichnis das gelöscht werden sol l
*/
private void deleteFile(File file)
throws IOException
{
if(file.isFile())
if
{
file.delete();
file
}
if
if(file.isDirectory())
{
// fileliste des verzeichnisses lesen
String[] filenames = file.list();
String
// durch die Files gehen und alle löschen
for(int i=0; i<filenames.length; i++)
for
deleteFile(new File(file.getPath() + "/" + filenames[i]));
deleteFile
// verzeichnis löschen
file.delete();
file
}
}
/**
* Diese Metode löscht einen Place samt allen darin enthaltenen Dateien .
*
* @param place der Place der gelöscht werden soll .
*/
public void deletePlace(String place)
throws RemoteException
{
try
{
// Place löschen
deleteFile(new File(basepath + "/" + place));
deleteFile
}
catch(IOException ioe)
catch
{
throw new RemoteException("mm: error deleting place", ioe);
}
}
/**
* Diese Methode wird vom Join Manager aufgerufen um dem Service sein e
Service ID mitzuteilen
mitzuteile
* so bald der Service registriert ist .
*
* @param service_id Service ID
I
*/
public void serviceIDNotify(ServiceID service_id)
{
System.out.print("Service registered, ID: ");
System
System.out.println(service_id);
System
}
/**
* Gibt true zurück wenn alles mit dem FileServer in Ordnung ist .
*
* @return true wenn alles mit dem FileServer in Ordnung ist .
*/
public boolean isAlive()
throws RemoteException
{
// check the database connection
try
{
// kleine Testquery
Connection conn = pool.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT checkvalue FROM
checktable");
if(rs.next())
if
{
String weltherrschaft = rs.getString("checkvalue");
if(weltherrschaft == null ||
if
!weltherrschaft.equalsIgnoreCase("WELTHERRSCHAFT"))
return false;
}
else
return false;
s.close();
conn.close();
conn
}
catch(SQLException sql)
catch
{
return false;
}
return true;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.files.RegisterFileServer
java.lang.Object
|
+----mm.services.files.RegisterFileServer
public class RegisterFileServer
extends java.lang.Object
Diese Klasse instantiiert den File server und registriert ihn beim Lookup
Service.
Version:
1.0
Author:
Stefan Zier
RegisterFileServer()
main(String[])
Main methode.
RegisterFileServer
public RegisterFileServer()
main
public static void main(java.lang.String argsv[])
Main methode.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.files;
// Java core imports
import java.rmi.*;
// Jini extension imports
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.lookup.entry.Name;
import net.jini.lookup.entry.ServiceInfo;
import net.jini.core.entry.Entry;
/**
* Diese Klasse instantiiert den File server und registriert ihn bei m
Lookup Service.
Service
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class RegisterFileServer
{
static JoinManager jm;
static FileServerImpl fileserver_instance;
/**
* Main methode.
*/
public static void main(String[] argsv)
{
System.out.println("RegisterFileServer (c) 1999 MM Jahresprojekt");
System
try
{
// install security manager so that we'll be able to talk to
server
System.out.println(">> installiere RMI Security manager...");
System
System.setSecurityManager(new RMISecurityManager());
System
// create service
System.out.println(">> instantiiere File Server ...");
System
fileserver_instance = new FileServerImpl();
// this name will be seen to users that browse services
Name nameEntry = new Name("MM File Server");
// some addtl. serivice information such as manufacterer etc.
ServiceInfo serviceInfo = new ServiceInfo("MM File Server", "CE5
WS 1999/2000",
"CE5 WS 1999/2000", "1.0", "", "");
// gather all information that we're going to pass on to the
lookup service
Entry entries[] = new Entry[] {nameEntry, serviceInfo};
System.out.println(">> registriere den File Server beim Lookup
System
Service...");
// create a new join manager and have it register the
jts_instance.
jm = new JoinManager(fileserver_instance, entries,
(ServiceIDListener) fileserver_instance, new LeaseRenewalManager());
System.out.println(">> File Server bereit");
System
}
catch(Exception e)
catch
{
System.out.println("##### mm: exception caught: ");
System
e.printStackTrace();
}
}
}
d.) mm.services.game
Dieses Package enthält Klassen des Spielmanager-Dienstes.
Klasse
Game
GameMaster
GameServer
GameServerImpl
Group
Player
RegisterGameServer
Bedeutung
Stellt ein Spiel dar
Stellt einen Spielleiter dar
Das Remote-Interface des SpielmanagerDienstes
Die Implementation des SpielmanagerDienstes
Stellt eine Gruppe dar
Stellt einen Spieler dar
Instantiiert einen Spielmanager-Dienst und
registriert ihn beim Lookup Service
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.Game
java.lang.Object
|
+----mm.services.game.Game
public class Game
extends java.lang.Object
implements java.io.Serializable
Diese Klasse speichert alle Informationen, die zu einem Spiel gehöeren,
wie Name der Spielübergreifenden File-places, Chatgroups, Messageboards,
etc.
Version:
1.0
Author:
Stefan Zier
Game(String, String, String, String, String, String)
Konstruktor.
getChatRoom()
Accessor für Chatroom
getFromGameMasterPlace()
Accessor für from_gm_place
getGameMaster()
Accessor für Gamemaster.
getName()
Accessor für Name
getNiceName()
Accessor für Nicename
getToGameMasterPlace()
Accessor für to_gm_place
Game
public Game(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
name,
nicename,
chatroom,
to_gm_place,
from_gm_place,
gamemaster)
Konstruktor.
Parameters:
name - der Name des Spiels
nicename - der Name des Spiels der auf dem Bildschirm angezeigt
wird
chatroom - der Name des Spielweiten Chatrooms
to_gm_place - der Name des File places auf den Dateien gelegt
werden die zum Spielleiter geschickt werden
from_gm_place - der Name des File places auf die der Spielleiter
Dateien legt die für alle Spieler da sind
gamemaster - der login des Gamemasters der das Spiel verwaltet
getName
public java.lang.String getName()
Accessor für Name
Returns:
den Namen des Spiels
getNiceName
public java.lang.String getNiceName()
Accessor für Nicename
Returns:
den Namen des Spieles wie er auf dem Bildschirm angezeigt
werden soll.
getChatRoom
public java.lang.String getChatRoom()
Accessor für Chatroom
Returns:
den Namen des Spielweiten Chatrooms
getToGameMasterPlace
public java.lang.String getToGameMasterPlace()
Accessor für to_gm_place
Returns:
den Namen des File Places der Benutzt wird um Daten von der
Gruppe an den Spielleiter zu schicken
getFromGameMasterPlace
public java.lang.String getFromGameMasterPlace()
Accessor für from_gm_place
Returns:
den Namen des File Places der benutzt wird um Dateien vom
Spielleiter an die Gruppe zu schicken
getGameMaster
public java.lang.String getGameMaster()
Accessor für Gamemaster.
Returns:
den Login des Gamemasters der das Spiel verwaltet
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
import java.io.Serializable;
/**
* Diese Klasse speichert alle Informationen, die zu einem Spiel gehöeren ,
wie Name
Nam
* der Spielübergreifenden File-places, Chatgroups, Messageboards, etc .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Game implements Serializable
{
private String name = null;
private String nicename = null;
private String chatroom = null;
private String to_gm_place = null;
private String from_gm_place = null;
private String gamemaster = null;
/**
* Konstruktor.
Konstruktor
*
* @param name der Name des Spiel s
* @param nicename der Name des Spiels der auf dem Bildschirm angezeig t
wird
wir
* @param chatroom der Name des Spielweiten Chatroom s
* @param to_gm_place der Name des File places auf den Dateien geleg t
werden die
*
zum Spielleiter geschickt werde n
* @param from_gm_place der Name des File places auf die der Spielleite r
Dateien legt
leg
*
die für alle Spieler da sin d
* @param gamemaster der login des Gamemasters der das Spiel verwalte t
*/
public Game(String name, String nicename, String chatroom, String
to_gm_place, String from_gm_place, String gamemaster)
{
this.name = name;
this
this.nicename = name;
this
this.chatroom = chatroom;
this
this.to_gm_place = to_gm_place;
this
this.from_gm_place = from_gm_place;
this
this.gamemaster = gamemaster;
this
}
/**
* Accessor für Name
Nam
*
* @return den Namen des Spiels
Spiel
*/
public String getName()
{
return name;
}
/**
* Accessor für Nicename
Nicenam
*
* @return den Namen des Spieles wie er auf dem Bildschirm angezeig t
werden soll.
soll
*/
public String getNiceName()
{
return nicename;
}
/**
* Accessor für Chatroom
Chatroo
*
* @return den Namen des Spielweiten Chatroom s
*/
public String getChatRoom()
{
return chatroom;
}
/**
* Accessor für to_gm_place
to_gm_plac
*
* @return den Namen des File Places der Benutzt wird um Daten von de r
Gruppe an den
de
*
Spielleiter zu schicke n
*/
public String getToGameMasterPlace()
{
return to_gm_place;
}
/**
* Accessor für from_gm_place
from_gm_plac
*
* @return den Namen des File Places der benutzt wird um Dateien vo m
Spielleiter an
a
*
die Gruppe zu schicke n
*/
public String getFromGameMasterPlace()
{
return from_gm_place;
}
/**
* Accessor für Gamemaster.
Gamemaster
*
* @return den Login des Gamemasters der das Spiel verwalte t
*/
public String getGameMaster()
{
return gamemaster;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.GameMaster
java.lang.Object
|
+----mm.services.game.GameMaster
public class GameMaster
extends java.lang.Object
implements java.io.Serializable
Der Spielleiter.
Version:
1.0
Author:
Stefan Zier
GameMaster(String, String, String, String, boolean)
Konstruktor
getEmail()
Accessor für
getLanguage()
Accessor für
getLogin()
Accessor für
getName()
Accessor für
isFirstLogin()
Accessor für
email.
Sprache
Login.
Name.
First Login.
GameMaster
public GameMaster(java.lang.String login,
java.lang.String name,
java.lang.String email,
java.lang.String language,
boolean first_login)
Konstruktor
Parameters:
login - der Login des Spielleiters
name - der Name des Spielleiters
email - die Email-Addresse des Spielleiters
getLogin
public java.lang.String getLogin()
Accessor für Login.
Returns:
den Login des Spielleiters
getLanguage
public java.lang.String getLanguage()
Accessor für Sprache
Returns:
die Sprache des Spielleiters
getName
public java.lang.String getName()
Accessor für Name.
Returns:
den Namen des Spielleiters.
getEmail
public java.lang.String getEmail()
Accessor für email.
Returns:
die Email Adresse des Spielleiters.
isFirstLogin
public boolean isFirstLogin()
Accessor für First Login.
Returns:
true wenn dies der erste Login des Spielleiters ist
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
import java.io.Serializable;
/**
* Der Spielleiter.
Spielleiter
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class GameMaster implements Serializable
{
private String login = null;
private String name = null;
private String email = null;
private String language = null;
private boolean first_login;
/**
* Konstruktor
Konstrukto
*
* @param login der Login des Spielleiter s
* @param name der Name des Spielleiter s
* @param email die Email-Addresse des Spielleiter s
*/
public GameMaster(String login, String name, String email, String
language, boolean first_login)
{
this.login = login;
this
this.name = name;
this
this.email = email;
this
this.language = language;
this
this.first_login = first_login;
this
}
/**
* Accessor für Login.
Login
*
* @return den Login des Spielleiters
Spielleiter
*/
public String getLogin()
{
return login;
}
/**
* Accessor für Sprache
Sprach
*
* @return die Sprache des Spielleiters
Spielleiter
*/
public String getLanguage()
{
return language;
}
/**
* Accessor für Name.
Name
*
* @return den Namen des Spielleiters.
Spielleiters
*/
public String getName()
{
return name;
}
/**
* Accessor für email.
email
*
* @return die Email Adresse des Spielleiters .
*/
public String getEmail()
{
return email;
}
/**
* Accessor für First Login.
Login
*
* @return true wenn dies der erste Login des Spielleiters is t
*/
public boolean isFirstLogin()
{
return first_login;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface mm.services.game.GameServer
public interface GameServer
extends java.rmi.Remote, AliveCheckable
Diese ist das Interface zum Spiel-Jini-Service. Der Webserver kommuniziert
ausschließlich über diese Schnittstelle zum Spielserver. Regeln: Spielernamen sind Applikationsweit eindeutig. - Spielnamen sind
Applikationsweit eindeutig. - Gruppennamen sind innerhalb eines Spieles
eindeutig. Deswegen muß hier immer noch das Spiel mit angegebeben
werden.
Version:
1.0
Author:
Stefan Zier
authenticateGameMaster(String, String)
Diese Methode authentifiziert einen Spielleiter.
authenticatePlayer(String, String)
Diese Methode dient dazu einen Spieler zu authentifizieren.
changeGameMaster(String, String)
Teilt einem Spiel einen neuen Spielleiter zu.
changeGameMasterEmail(String, String)
Ändert die Email Adresse eines Spielleiters.
changeGameMasterLanguage(String, String)
Ändert die Sprache eines Spielleiters.
changeGameMasterPassword(String, String)
Ändert das Passwort eines Spielleiters.
changePlayerEmail(String, String)
Ändert die Email-Addresse eines Spielers.
changePlayerLanguage(String, String)
Diese Methode ändert die Sprache eines Spielers.
changePlayerPassword(String, String)
Diese Methode ändert das Passwort eines Spielers.
createGame(String, String, String)
Diese Methode erstellt ein neues Spiel.
createGameMaster(String, String, String, String)
Fügt einen GameMaster hinzu
createGroup(String, String, String)
Diese Methode erstellt eine Gruppe.
createPlayer(String, String, String, String, String, String)
Diese Methode erstellt einen neuen Spieler.
deleteGame(String)
Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen.
deleteGameMaster(String)
Löscht einen GameMaster
deleteGroup(String, String)
Diese Methode löscht eine Gruppe und all deren Mitspieler.
deletePlayer(String)
Löscht einen Spieler.
getGame(String)
Diese Methode sucht informationen zu einem Spiel und liefert es
zurück.
getGameMaster(String)
Liest einen Spielleiter aus der Datenbank
getGroup(String, String)
Diese Methode sucht Informationen zu einer Gruppe und liefert ein
Group-Objekt zurück.
getPlayer(String)
Sucht informationen über einen Spieler und liefert sie in Form eines
Player-Objektes zurück.
listGameMasters()
Generiert eine Liste der GameMasters
listGames()
Listet alle Spiele applikationsweit auf.
listGroups()
Listet alle Gruppen applikationsweit auf.
listGroups(String)
Listet alle Gruppen in einem Spiel auf.
listPlayers()
Listet alle Spieler applikationsweit auf.
listPlayers(String)
Listet alle Spieler eines Spiels auf.
listPlayers(String, String)
Listet alle Spieler einer Gruppe auf.
sendGameMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an alle Mitglieder eines Spiels
sendGameMasterMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an einen SpielLeiter
sendGroupMail(String, String, String, String, String, Hashtable)
Verschickt ein Mail Template an alle Mitlieder einer Gruppe
sendPasswordMail(String)
Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ihm sein
Passwort mit.
sendPlayerMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an einen Spieler
authenticatePlayer
public Player authenticatePlayer(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExceptio
Diese Methode dient dazu einen Spieler zu authentifizieren. Sie
liefert als Rückgabewert ein Player Objekt, mit dem alle Informationen zu
einem Spieler zugänglich sind.
Parameters:
login - Der username
password - Das Passwort
Returns:
null wenn der Nutzer unbekannt ist, ansonsten das Player-Objekt
authenticateGameMaster
public GameMaster authenticateGameMaster(java.lang.String login,
java.lang.String password) throws java.rmi.Remote
Diese Methode authentifiziert einen Spielleiter. Der Rückgabewert
ist ein GameMaster objekt.
Parameters:
login - der Login des Spielleiters
password - das Passwort
Returns:
null wenn der Nutzer unbekannt ist, ansonsten das GameMasterObjekt
createGame
public Game createGame(java.lang.String name,
java.lang.String nicename,
java.lang.String gamemaster) throws java.rmi.RemoteException
Diese Methode erstellt ein neues Spiel.
Parameters:
name - der Name des Spiels
nicename - der Name des Spiels der auf dem Bildschirm dargestellt
wird
gamemaster - das Login des Spielleiters, der das Spiel leitet
Returns:
das Game-Objekt
deleteGame
public void deleteGame(java.lang.String name) throws java.rmi.RemoteException
Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen.
Parameters:
name - der Name des Spiels
changeGameMaster
public void changeGameMaster(java.lang.String game,
java.lang.String gamemaster) throws java.rmi.RemoteException
Teilt einem Spiel einen neuen Spielleiter zu.
Parameters:
game - der
gamemaster
Name des Spiels
- der Name des neuen Spielleiters
getGame
public Game getGame(java.lang.String name) throws java.rmi.RemoteException
Diese Methode sucht informationen zu einem Spiel und liefert es
zurück.
Parameters:
name - der Name des Spiels
Returns:
das Game-Objekt oder null wenn das Spiel nicht existiert
listGames
public java.util.Vector listGames() throws java.rmi.RemoteException
Listet alle Spiele applikationsweit auf.
Returns:
einen Vector der Game-Objekte enthält.
createGroup
public Group createGroup(java.lang.String name,
java.lang.String nicename,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode erstellt eine Gruppe.
Parameters:
name - der Name der Gruppe
nicename - der Name der Gruppe wie er auf dem Bildschirm
dargestellt wird
game - der Name des Spiels zu der die Gruppe gehört
deleteGroup
public void deleteGroup(java.lang.String name,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode löscht eine Gruppe und all deren Mitspieler.
Parameters:
name - der Name der Gruppe
game - der Name des SPiels zu dem die Gruppe gehört
getGroup
public Group getGroup(java.lang.String name,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode sucht Informationen zu einer Gruppe und liefert ein
Group-Objekt zurück.
Parameters:
name - der Name der Gruppe
game - der Name des Spiels zu dem die Gruppe gehört
Returns:
null, wenn die Gruppe nicht gefunden wurde, sonst das GroupObjekt
listGroups
public java.util.Vector listGroups(java.lang.String game) throws java.rmi.RemoteException
Listet alle Gruppen in einem Spiel auf.
Parameters:
game - das Spiel
Returns:
einen Vector, der Group-Objekte enthält
listGroups
public java.util.Vector listGroups() throws java.rmi.RemoteException
Listet alle Gruppen applikationsweit auf.
Returns:
einen Vector, der Group-Objekte enthält
createPlayer
public Player createPlayer(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
login,
name,
email,
group,
game,
language) throws java.rmi.RemoteException
Diese Methode erstellt einen neuen Spieler.
Parameters:
login - der login des Spielers
name - der Name des Spielers
emael - die E-Mail-Addresse des Spielers
group - der Name der Gruppe zu der der Spieler gehört
game - der Name des Spiels zu dem die Gruppe gehört
language - das 2-Buchstaben-Kürzel der Sprache in der der Spieler
die Webseiten anschaut
changePlayerPassword
public void changePlayerPassword(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExceptio
Diese Methode ändert das Passwort eines Spielers.
Parameters:
login - der Login des Spielers
password - das neue Passwort des Spielers
changePlayerLanguage
public void changePlayerLanguage(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExceptio
Diese Methode ändert die Sprache eines Spielers.
Parameters:
login - der Login des Spielers
language - die neue Sprache des Spielers
changePlayerEmail
public void changePlayerEmail(java.lang.String login,
java.lang.String email) throws java.rmi.RemoteException
Ändert die Email-Addresse eines Spielers.
Parameters:
login - der Login des Spielers
email - die neue Email des Spielers
deletePlayer
public void deletePlayer(java.lang.String login) throws java.rmi.RemoteException
Löscht einen Spieler.
Parameters:
login - der login des Spielers.
getPlayer
public Player getPlayer(java.lang.String login) throws java.rmi.RemoteException
Sucht informationen über einen Spieler und liefert sie in Form eines
Player-Objektes zurück.
Parameters:
login - der login des Spielers
listPlayers
public java.util.Vector listPlayers(java.lang.String group,
java.lang.String game) throws java.rmi.RemoteException
Listet alle Spieler einer Gruppe auf.
Parameters:
group - die Gruppe
game - das Spiel
Returns:
einen Vector mit Player-Objekten
listPlayers
public java.util.Vector listPlayers(java.lang.String game) throws java.rmi.RemoteException
Listet alle Spieler eines Spiels auf.
Parameters:
game - das Spiel
Returns:
einen Vector mit Player-Objekten
listPlayers
public java.util.Vector listPlayers() throws java.rmi.RemoteException
Listet alle Spieler applikationsweit auf.
Returns:
einen Vector mit Player-Objekten
createGameMaster
public GameMaster createGameMaster(java.lang.String
java.lang.String
java.lang.String
java.lang.String
login,
email,
name,
language) throws java.rmi.RemoteExcept
Fügt einen GameMaster hinzu
Parameters:
login - der Login des neuen GameMasters
email - die Email des neuen GameMasters
name - der Name des neuen GameMasters
language - die Sprache des neuen GameMasters
Returns:
den neuen GameMaster oder null
deleteGameMaster
public void deleteGameMaster(java.lang.String login) throws java.rmi.RemoteException
Löscht einen GameMaster
Parameters:
login - der Login des GameMasters der gelöscht werden soll
listGameMasters
public java.util.Vector listGameMasters() throws java.rmi.RemoteException
Generiert eine Liste der GameMasters
Returns:
einen Vector mit GameMaster-Objekten
changeGameMasterPassword
public void changeGameMasterPassword(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExce
Ändert das Passwort eines Spielleiters.
Parameters:
login - der Login des Spielleiters
password - das neue Passwort des Spielleiters
changeGameMasterEmail
public void changeGameMasterEmail(java.lang.String login,
java.lang.String email) throws java.rmi.RemoteException
Ändert die Email Adresse eines Spielleiters.
Parameters:
login - der Login des Spielleiters
email - die neue Email des Spielleiters
changeGameMasterLanguage
public void changeGameMasterLanguage(java.lang.String login,
java.lang.String language) throws java.rmi.RemoteExce
Ändert die Sprache eines Spielleiters.
Parameters:
login - der Login des Spielleiters
language - die neue Sprache des Spielleiters
getGameMaster
public GameMaster getGameMaster(java.lang.String login) throws java.rmi.RemoteException
Liest einen Spielleiter aus der Datenbank
Parameters:
login - der Login des Spielleiters
sendGameMail
public void sendGameMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String game,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an alle Mitglieder eines Spiels
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
game - der Name des Spiels
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendGroupMail
public void sendGroupMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String game,
java.lang.String group,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an alle Mitlieder einer Gruppe
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
game - der Name des Spiels
group - der Name der Gruppe
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendPlayerMail
public void sendPlayerMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String login,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an einen Spieler
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
login - Login des Spielers
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendGameMasterMail
public void sendGameMasterMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String login,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteExceptio
Verschickt ein Mail Template an einen SpielLeiter
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
login - Login des Spielleiters
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendPasswordMail
public void sendPasswordMail(java.lang.String login) throws java.rmi.RemoteException
Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ihm
sein Passwort mit.
Parameters:
login - der Login des Spielleiters oder Spielers
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
import
import
import
import
java.util.Hashtable;
java.util.Vector;
java.rmi.Remote;
java.rmi.RemoteException;
import mm.tools.AliveCheckable;
/**
* Diese ist das Interface zum Spiel-Jini-Service. Der Webserve r
* kommuniziert ausschließlich über diese Schnittstelle zum
* Spielserver.
*
* Regeln:
Regeln
*
* - Spielernamen sind Applikationsweit eindeutig.
eindeutig
* - Spielnamen sind Applikationsweit eindeutig.
* - Gruppennamen sind innerhalb eines Spieles eindeutig. Deswegen muß hie r
immer
imme
*
noch das Spiel mit angegebeben werden .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public interface GameServer extends Remote, AliveCheckable
{
/**
* Diese Methode dient dazu einen Spieler zu authentifizieren. Si e
* liefert als Rückgabewert ein Player Objekt, mit dem all e
Informationen
Informatione
* zu einem Spieler zugänglich sind.
*
* @param login Der username
usernam
* @param password Das Passwort
Passwor
* @return null wenn der Nutzer unbekannt ist, ansonsten da s
Player-Objekt
Player-Objek
*/
public Player authenticatePlayer(String login, String password)
throws RemoteException;
/**
* Diese Methode authentifiziert einen Spielleiter. Der Rückgabewert is t
ei
ein
* GameMaster objekt.
objekt
*
* @param login der Login des Spielleiter s
* @param password das Passwort
Passwor
* @return null wenn der Nutzer unbekannt ist, ansonsten da s
GameMaster-Objekt
GameMaster-Objek
*/
public GameMaster authenticateGameMaster(String login, String password)
throws RemoteException;
/**
* Diese Methode erstellt ein neues Spiel.
*
* @param name der Name des Spiel s
* @param nicename der Name des Spiels der auf dem Bildschir m
dargestellt wird
wir
* @param gamemaster das Login des Spielleiters, der das Spiel leite t
* @return das Game-Objekt
Game-Objek
*/
public Game createGame(String name, String nicename, String gamemaster)
throws RemoteException;
/**
* Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen .
*
* @param name der Name des Spiel s
*/
public void deleteGame(String name
name)
throws RemoteException;
/**
* Teilt einem Spiel einen neuen Spielleiter zu .
*
* @param game der Name des Spiel s
* @param gamemaster der Name des neuen Spielleiter s
*/
public void changeGameMaster(String game, String gamemaster)
throws RemoteException;
/**
* Diese Methode sucht informationen zu einem Spiel und liefert e s
* zurück.
zurück
*
* @param name der Name des Spiel s
* @return das Game-Objekt oder null wenn das Spiel nicht existier t
*/
public Game getGame(String name)
throws RemoteException;
/**
* Listet alle Spiele applikationsweit auf.
auf
*
* @return einen Vector der Game-Objekte enthält .
*/
public Vector listGames()
throws RemoteException;
/**
* Diese Methode erstellt eine Gruppe.
Gruppe
*
* @param name der Name der Grupp e
* @param nicename der Name der Gruppe wie er auf dem Bildschir m
dargestellt wird
wir
* @param game der Name des Spiels zu der die Gruppe gehör t
*/
public Group createGroup(String name, String nicename, String game)
throws RemoteException;
/**
* Diese Methode löscht eine Gruppe und all deren Mitspieler .
*
* @param name der Name der Grupp e
* @param game der Name des SPiels zu dem die Gruppe gehör t
*/
public void deleteGroup(String name, String game)
throws RemoteException;
/**
* Diese Methode sucht Informationen zu einer Gruppe und liefert ei n
* Group-Objekt zurück.
zurück
*
* @param name der Name der Grupp e
* @param game der Name des Spiels zu dem die Gruppe gehör t
* @return null, wenn die Gruppe nicht gefunden wurde, sonst da s
Group-Objekt
Group-Objek
*/
public Group getGroup(String name, String game)
throws RemoteException;
/**
* Listet alle Gruppen in einem Spiel auf .
*
* @param game das Spiel
Spie
* @return einen Vector, der Group-Objekte enthäl t
*/
public Vector listGroups(String game)
throws RemoteException;
/**
* Listet alle Gruppen applikationsweit auf.
auf
*
* @return einen Vector, der Group-Objekte enthäl t
*/
public Vector listGroups()
throws RemoteException;
/**
* Diese Methode erstellt einen neuen Spieler.
*
* @param login der login des Spieler s
* @param name der Name des Spieler s
* @param emael die E-Mail-Addresse des Spieler s
* @param group der Name der Gruppe zu der der Spieler gehör t
* @param game der Name des Spiels zu dem die Gruppe gehör t
* @param language das 2-Buchstaben-Kürzel der Sprache in der de r
Spieler die Webseiten anschaut
anschau
*/
public Player createPlayer(String login, String name, String email,
String group, String game, String language)
throws RemoteException;
/**
* Diese Methode ändert das Passwort eines Spielers .
*
* @param login der Login des Spieler s
* @param password das neue Passwort des Spieler s
*/
public void changePlayerPassword(String login, String password)
throws RemoteException;
/**
* Diese Methode ändert die Sprache eines Spielers .
*
* @param login der Login des Spieler s
* @param language die neue Sprache des Spieler s
*/
public void changePlayerLanguage(String login, String password)
throws RemoteException;
/**
* Ändert die Email-Addresse eines Spielers.
Spielers
*
* @param login der Login des Spieler s
* @param email die neue Email des Spieler s
*/
public void changePlayerEmail(String login, String email)
throws RemoteException;
/**
* Löscht einen Spieler.
Spieler
*
* @param login der login des Spielers .
*/
public void deletePlayer(String login)
throws RemoteException;
/**
* Sucht informationen über einen Spieler und liefert sie in Form eine s
* Player-Objektes zurück.
zurück
*
* @param login der login des Spieler s
*/
public Player getPlayer(String login)
throws RemoteException;
/**
* Listet alle Spieler einer Gruppe auf .
*
* @param group die Gruppe
Grupp
* @param game das Spiel
Spie
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers(String group, String game)
throws RemoteException;
/**
* Listet alle Spieler eines Spiels auf .
*
* @param game das Spiel
Spie
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers(String game)
throws RemoteException;
/**
* Listet alle Spieler applikationsweit auf.
auf
*
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers()
throws RemoteException;
/**
* Fügt einen GameMaster hinzu
hinz
*
* @param login der Login des neuen GameMaster s
* @param email die Email des neuen GameMaster s
* @param name der Name des neuen GameMaster s
* @param language die Sprache des neuen GameMaster s
* @return den neuen GameMaster oder nul l
*/
public GameMaster createGameMaster(String login, String email, String
name, String language)
throws RemoteException;
/**
* Löscht einen GameMaster
GameMaste
*
* @param login der Login des GameMasters der gelöscht werden sol l
*/
public void deleteGameMaster(String login)
throws RemoteException;
/**
* Generiert eine Liste der GameMasters
GameMaster
*
* @return einen Vector mit GameMaster-Objekten
GameMaster-Objekte
*/
public Vector listGameMasters()
throws RemoteException;
/**
* Ändert das Passwort eines Spielleiters.
Spielleiters
*
* @param login der Login des Spielleiter s
* @param password das neue Passwort des Spielleiter s
*/
public void changeGameMasterPassword(String login, String password)
throws RemoteException;
/**
* Ändert die Email Adresse eines Spielleiters .
*
* @param login der Login des Spielleiter s
* @param email die neue Email des Spielleiter s
*/
public void changeGameMasterEmail(String login, String email)
throws RemoteException;
/**
* Ändert die Sprache eines Spielleiters.
Spielleiters
*
* @param login der Login des Spielleiter s
* @param language die neue Sprache des Spielleiter s
*/
public void changeGameMasterLanguage(String login, String language)
throws RemoteException;
/**
* Liest einen Spielleiter aus der Datenban k
*
* @param login der Login des Spielleiter s
*/
public GameMaster getGameMaster(String login)
throws RemoteException;
/**
* Verschickt ein Mail Template an alle Mitglieder eines Spiel s
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param game der Name des Spiels
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGameMail(String snd_email, String snd_name, String game,
String template, Hashtable strings)
throws RemoteException;
/**
* Verschickt ein Mail Template an alle Mitlieder einer Grupp e
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param game der Name des Spiels
* @param group der Name der Gruppe
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGroupMail(String snd_email, String snd_name, String
game, String group, String template, Hashtable strings)
throws RemoteException;
/**
* Verschickt ein Mail Template an einen Spiele r
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param login Login des Spielers
Spieler
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendPlayerMail(String snd_email, String snd_name, String
login, String template, Hashtable strings)
throws RemoteException;
/**
* Verschickt ein Mail Template an einen SpielLeite r
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param login Login des Spielleiters
Spielleiter
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGameMasterMail(String snd_email, String snd_name, String
login, String template, Hashtable strings)
throws RemoteException;
/**
* Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ih m
sein Passwort mit.
mit
*
* @param login der Login des Spielleiters oder Spieler s
*/
public void sendPasswordMail(String login)
throws RemoteException;
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.GameServerImpl
mm.services.game.GameServerImpl
public class GameServerImpl
implements GameServer
Implementation des Gameservers. Im großen und ganzen nur 1.000de
Datenbank-queries
Version:
1.0
Author:
Stefan Zier
WEBMASTER_EMAIL
WEBMASTER_NAME
GameServerImpl()
Konstruktor.
authenticateGameMaster(String, String)
Diese Methode authentifiziert einen Spielleiter.
authenticatePlayer(String, String)
Diese Methode dient dazu einen Spieler zu authentifizieren.
changeGameMaster(String, String)
Teilt einem Spiel einen neuen Spielleiter zu.
changeGameMasterEmail(String, String)
Ändert die Email Adresse eines Spielleiters.
changeGameMasterLanguage(String, String)
Ändert die Sprache eines Spielleiters.
changeGameMasterPassword(String, String)
Ändert das Passwort eines Spielleiters.
changePlayerEmail(String, String)
Ändert die Email-Addresse eines Spielers.
changePlayerLanguage(String, String)
Diese Methode ändert die Sprache eines Spielers.
changePlayerPassword(String, String)
Diese Methode ändert das Passwort eines Spielers.
createGame(String, String, String)
Diese Methode erstellt ein neues Spiel.
createGameMaster(String, String, String, String)
Fügt einen GameMaster hinzu
createGroup(String, String, String)
Diese Methode erstellt eine Gruppe.
createPlayer(String, String, String, String, String, String)
Diese Methode erstellt einen neuen Spieler.
deleteGame(String)
Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen.
deleteGameMaster(String)
Löscht einen GameMaster
deleteGroup(String, String)
Diese Methode löscht eine Gruppe und all deren Mitspieler.
deletePlayer(String)
Löscht einen Spieler.
getGame(String)
Diese Methode sucht informationen zu einem Spiel und liefert es
zurück.
getGameMaster(String)
Liest einen Spielleiter aus der Datenbank
getGroup(String, String)
Diese Methode sucht Informationen zu einer Gruppe und liefert ein
Group-Objekt zurück.
getPlayer(String)
Sucht informationen über einen Spieler und liefert sie in Form eines
Player-Objektes zurück.
isAlive()
Gibt true zurück wenn alles mit dem FileServer in Ordnung ist.
listGameMasters()
Generiert eine Liste der GameMasters
listGames()
Listet alle Spiele applikationsweit auf.
listGroups()
Listet alle Gruppen applikationsweit auf.
listGroups(String)
Listet alle Gruppen in einem Spiel auf.
listPlayers()
Listet alle Spieler applikationsweit auf.
listPlayers(String)
Listet alle Spieler eines Spiels auf.
listPlayers(String, String)
Listet alle Spieler einer Gruppe auf.
sendGameMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an alle Mitglieder eines Spiels
sendGameMasterMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an einen SpielLeiter
sendGroupMail(String, String, String, String, String, Hashtable)
Verschickt ein Mail Template an alle Mitlieder einer Gruppe
sendPasswordMail(String)
Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ihm sein
Passwort mit.
sendPlayerMail(String, String, String, String, Hashtable)
Verschickt ein Mail Template an einen Spieler
serviceIDNotify(ServiceID)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
WEBMASTER_EMAIL
public final java.lang.String WEBMASTER_EMAIL
WEBMASTER_NAME
public final java.lang.String WEBMASTER_NAME
GameServerImpl
public GameServerImpl() throws java.rmi.RemoteException, java.sql.SQLException, java.io.IO
auf.
Konstruktor. Baut Verbindungen zur Datenbank und zum Mailserver
authenticatePlayer
public Player authenticatePlayer(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExceptio
Diese Methode dient dazu einen Spieler zu authentifizieren. Sie
liefert als Rückgabewert ein Player Objekt, mit dem alle Informationen zu
einem Spieler zugänglich sind. Setzt ggf. FirstLogin auf false.
Parameters:
login - Der username
password - Das Passwort
Returns:
null wenn der Nutzer unbekannt ist, ansonsten das Player-Objekt
authenticateGameMaster
public GameMaster authenticateGameMaster(java.lang.String login,
java.lang.String password) throws java.rmi.Remote
Diese Methode authentifiziert einen Spielleiter. Der Rückgabewert
ist ein GameMaster objekt.
Parameters:
login - der Login des Spielleiters
password - das Passwort
Returns:
null wenn der Nutzer unbekannt ist, ansonsten das GameMasterObjekt
createGame
public Game createGame(java.lang.String name,
java.lang.String nicename,
java.lang.String gamemaster) throws java.rmi.RemoteException
Diese Methode erstellt ein neues Spiel.
Parameters:
name - der Name des Spiels
nicename - der Name des Spiels der auf dem Bildschirm dargestellt
wird
gamemaster - das Login des Spielleiters, der das Spiel leitet
Returns:
das Game-Objekt
deleteGame
public void deleteGame(java.lang.String name) throws java.rmi.RemoteException
Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen.
Parameters:
name - der Name des Spiels
changeGameMaster
public void changeGameMaster(java.lang.String game,
java.lang.String gamemaster) throws java.rmi.RemoteException
Teilt einem Spiel einen neuen Spielleiter zu.
Parameters:
game - der Name des Spiels
gamemaster - der Name des neuen Spielleiters
getGame
public Game getGame(java.lang.String name) throws java.rmi.RemoteException
Diese Methode sucht informationen zu einem Spiel und liefert es
zurück.
Parameters:
name - der Name des Spiels
Returns:
das Game-Objekt oder null wenn das Spiel nicht existiert
listGames
public java.util.Vector listGames() throws java.rmi.RemoteException
Listet alle Spiele applikationsweit auf.
Returns:
einen Vector der Game-Objekte enthält.
createGroup
public Group createGroup(java.lang.String name,
java.lang.String nicename,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode erstellt eine Gruppe.
Parameters:
name - der Name der Gruppe
nicename - der Name der Gruppe wie er auf dem Bildschirm
dargestellt wird
game - der Name des Spiels zu der die Gruppe gehört
deleteGroup
public void deleteGroup(java.lang.String name,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode löscht eine Gruppe und all deren Mitspieler.
Parameters:
name - der Name der Gruppe
game - der Name des SPiels zu dem die Gruppe gehört
getGroup
public Group getGroup(java.lang.String name,
java.lang.String game) throws java.rmi.RemoteException
Diese Methode sucht Informationen zu einer Gruppe und liefert ein
Group-Objekt zurück.
Parameters:
name - der Name der Gruppe
game - der Name des Spiels zu dem die Gruppe gehört
Returns:
null, wenn die Gruppe nicht gefunden wurde, sonst das GroupObjekt
listGroups
public java.util.Vector listGroups(java.lang.String game) throws java.rmi.RemoteException
Listet alle Gruppen in einem Spiel auf.
Parameters:
game - das Spiel
Returns:
einen Vector, der Group-Objekte enthält
listGroups
public java.util.Vector listGroups() throws java.rmi.RemoteException
Listet alle Gruppen applikationsweit auf.
Returns:
einen Vector, der Group-Objekte enthält
createPlayer
public Player createPlayer(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
login,
name,
email,
group,
game,
language) throws java.rmi.RemoteException
Diese Methode erstellt einen neuen Spieler.
Parameters:
login - der login des Spielers
name - der Name des Spielers
email - die E-Mail-Addresse des Spielers
group - der Name der Gruppe zu der der Spieler gehört
game - der Name des Spiels zu dem die Gruppe gehört
language - das 2-Buchstaben-Kürzel der Sprache in der der Spieler
die Webseiten anschaut
changePlayerPassword
public void changePlayerPassword(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExceptio
Diese Methode ändert das Passwort eines Spielers.
Parameters:
login - der Login des Spielers
password - das neue Passwort des Spielers
changePlayerLanguage
public void changePlayerLanguage(java.lang.String login,
java.lang.String language) throws java.rmi.RemoteExceptio
Diese Methode ändert die Sprache eines Spielers.
Parameters:
login - der Login des Spielers
language - die neue Sprache des Spielers
changePlayerEmail
public void changePlayerEmail(java.lang.String login,
java.lang.String email) throws java.rmi.RemoteException
Ändert die Email-Addresse eines Spielers.
Parameters:
login - der Login des Spielers
email - die neue Email des Spielers
deletePlayer
public void deletePlayer(java.lang.String login) throws java.rmi.RemoteException
Löscht einen Spieler.
Parameters:
login - der login des Spielers.
getPlayer
public Player getPlayer(java.lang.String login) throws java.rmi.RemoteException
Sucht informationen über einen Spieler und liefert sie in Form eines
Player-Objektes zurück.
Parameters:
login - der login des Spielers
listPlayers
public java.util.Vector listPlayers(java.lang.String group,
java.lang.String game) throws java.rmi.RemoteException
Listet alle Spieler einer Gruppe auf.
Parameters:
group - die Gruppe
game - das Spiel
Returns:
einen Vector mit Player-Objekten
listPlayers
public java.util.Vector listPlayers(java.lang.String game) throws java.rmi.RemoteException
Listet alle Spieler eines Spiels auf.
Parameters:
game - das Spiel
Returns:
einen Vector mit Player-Objekten
listPlayers
public java.util.Vector listPlayers() throws java.rmi.RemoteException
Listet alle Spieler applikationsweit auf.
Returns:
einen Vector mit Player-Objekten
createGameMaster
public GameMaster createGameMaster(java.lang.String
java.lang.String
java.lang.String
java.lang.String
login,
email,
name,
language) throws java.rmi.RemoteExcept
Fügt einen GameMaster hinzu
Parameters:
login - der Login des neuen GameMasters
email - die Email des neuen GameMasters
name - der Name des neuen GameMasters
language - die Sprache des neuen Spielleiters
Returns:
den neuen GameMaster oder null
deleteGameMaster
public void deleteGameMaster(java.lang.String login) throws java.rmi.RemoteException
Löscht einen GameMaster
Parameters:
login - der Login des GameMasters der gelöscht werden soll
listGameMasters
public java.util.Vector listGameMasters() throws java.rmi.RemoteException
Generiert eine Liste der GameMasters
Returns:
einen Vector mit GameMaster-Objekten
changeGameMasterPassword
public void changeGameMasterPassword(java.lang.String login,
java.lang.String password) throws java.rmi.RemoteExce
Ändert das Passwort eines Spielleiters.
Parameters:
login - der Login des Spielleiters
password - das neue Passwort des Spielleiters
changeGameMasterEmail
public void changeGameMasterEmail(java.lang.String login,
java.lang.String email) throws java.rmi.RemoteException
Ändert die Email Adresse eines Spielleiters.
Parameters:
login - der Login des Spielleiters
email - die neue Email des Spielleiters
changeGameMasterLanguage
public void changeGameMasterLanguage(java.lang.String login,
java.lang.String language) throws java.rmi.RemoteExce
Ändert die Sprache eines Spielleiters.
Parameters:
login - der Login des Spielleiters
language - die neue Sprache des Spielleiters
getGameMaster
public GameMaster getGameMaster(java.lang.String login) throws java.rmi.RemoteException
Liest einen Spielleiter aus der Datenbank
Parameters:
login - der Login des SPielleiters
Returns:
den Spielleiter
sendGameMail
public void sendGameMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String game,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an alle Mitglieder eines Spiels
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
game - der Name des Spiels
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendGroupMail
public void sendGroupMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String game,
java.lang.String group,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an alle Mitlieder einer Gruppe
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
game - der Name des Spiels
group - der Name der Gruppe
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendPlayerMail
public void sendPlayerMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String login,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteException
Verschickt ein Mail Template an einen Spieler
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
login - Login des Spielers
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendGameMasterMail
public void sendGameMasterMail(java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String login,
java.lang.String template,
java.util.Hashtable strings) throws java.rmi.RemoteExceptio
Verschickt ein Mail Template an einen SpielLeiter
Parameters:
snd_email - der Absender der email
snd_name - der Name des Absenders
login - Login des SpielLeiters
template - das Template das geschickt werden soll
strings - Werte die in die Mail geparst werden sollen oder null
wenn keine Werte geparst werden sollen
sendPasswordMail
public void sendPasswordMail(java.lang.String login) throws java.rmi.RemoteException
Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ihm
sein Passwort mit.
Parameters:
login - der Login des Spielleiters oder Spielers
serviceIDNotify
public void serviceIDNotify(net.jini.core.lookup.ServiceID service_id)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
Parameters:
service_id - Service ID
isAlive
public boolean isAlive() throws java.rmi.RemoteException
Gibt true zurück wenn alles mit dem FileServer in Ordnung ist.
Returns:
true wenn alles mit dem FileServer in Ordnung ist.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
// Java core imports
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.io.IOException;
import java.util.Vector;
import java.util.Random;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Enumeration;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
// Database connection imports
import com.bitmechanic.sql.ConnectionPoolManager;
import com.bitmechanic.sql.ConnectionPool;
// Jini extension imports
import com.sun.jini.lookup.ServiceIDListener;
import net.jini.core.lookup.ServiceID;
// MM Project imports
import mm.tools.ConfigFile;
import mm.tools.Static;
import mm.jini.ServiceController;
// MM Services imports
import mm.services.files.FileServer;
import mm.services.mailer.MailServer;
/**
* Implementation des Gameservers. Im großen und ganzen nur 1.000d e
Datenbank-queries
Datenbank-querie
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class GameServerImpl extends UnicastRemoteObject implements
GameServer, ServiceIDListener
{
// name und email für die Passwort-Vergessen-Mails
public final String WEBMASTER_EMAIL = "[email protected]";
public final String WEBMASTER_NAME = "System";
// namen der Service-Klassen
private final String FILE_SERVER = "mm.services.files.FileServer";
private final String MAIL_SERVER = "mm.services.mailer.MailServer";
// database connections
private ConnectionPoolManager cpm = null;
private ConnectionPool pool = null;
;
// jini service controller
private ServiceController service_controller = null;
private Random random = null;
/**
* Konstruktor. Baut Verbindungen zur Datenbank und zum Mailserver auf .
*/
public GameServerImpl()
throws RemoteException, SQLException, IOException,
ClassNotFoundException,
InstantiationException, IllegalAccessException
InstantiationException
{
super();
super
ConfigFile configfile = new
ConfigFile("f:\\mm\\services\\game\\gameserver.properties");
// create a connection pool manager
cpm = new ConnectionPoolManager(120);
// get
String
String
String
url, username and password from the configuration file
url = configfile.get("gameserver.database.URL");
username = configfile.get("gameserver.database.username");
password = configfile.get("gameserver.database.password");
if
if(url
== null || url.equals(""))
{
throw new IllegalArgumentException("mm: no database URL given");
}
if(username == null || username.equals(""))
if
{
throw new IllegalArgumentException("mm: no database login given");
}
if(password == null || password.equals(""))
if
{
throw new IllegalArgumentException("mm: no database password
given");
}
// add the alias for "our" database
cpm.addAlias("gameserver", "org.gjt.mm.mysql.Driver", url, username,
cpm
password, 120, 300, 120);
pool = cpm.getPool("gameserver");
// service controller instantiieren
service_controller = new ServiceController();
// anmelden welche Services wir brauchen
service_controller.addSearchClass(MAIL_SERVER);
service_controller
service_controller.addSearchClass(FILE_SERVER);
service_controller
// Zufallsgenerator initialisieren
random = new Random();
}
/**
* Diese Methode dient dazu einen Spieler zu authentifizieren. Si e
* liefert als Rückgabewert ein Player Objekt, mit dem all e
Informationen
Informatione
* zu einem Spieler zugänglich sind. Setzt ggf. FirstLogin auf false .
*
* @param login Der username
usernam
* @param password Das Passwort
Passwor
* @return null wenn der Nutzer unbekannt ist, ansonsten da s
Player-Objekt
Player-Objek
*/
public Player authenticatePlayer(String login, String password)
throws RemoteException
{
Player result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, pgroup, language, game, email,
first_login FROM player WHERE login=";
query += Static.sqlString(login) + " AND password=" +
Static.sqlString(password);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String name = rs.getString("name");
String group = rs.getString("group");
String language = rs.getString("language");
String game = rs.getString("game");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
result = new Player(login, name, group, game, email, language,
first_login == 1);
}
// Statement schliessen
s.close();
();
// Prüfen ob dies der erste login des Spielers ist
if(result.isFirstLogin())
if
{
// flag in der datenbank auf 0 setzen
query = "UPDATE players SET first_login=0 WHERE login=" +
Static.sqlString(login);
s = conn.createStatement();
s.execute(query);
s.close();
}
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Diese Methode authentifiziert einen Spielleiter. Der Rückgabewert is t
ei
ein
* GameMaster objekt.
objekt
*
* @param login der Login des Spielleiter s
* @param password das Passwort
Passwor
* @return null wenn der Nutzer unbekannt ist, ansonsten da s
GameMaster-Objekt
GameMaster-Objek
*/
public GameMaster authenticateGameMaster(String login, String password)
throws RemoteException
{
GameMaster result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, email, first_login, language FROM
gamemasters WHERE login=";
query += Static.sqlString(login) + " AND password=" +
Static.sqlString(password);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String name = rs.getString("name");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
String language = rs.getString("language");
// GameMaster erzeugen
result = new GameMaster(login, name, email, language,
first_login == 1);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Diese Methode erstellt ein neues Spiel.
*
* @param name der Name des Spiel s
* @param nicename der Name des Spiels der auf dem Bildschir m
dargestellt wird
wir
* @param gamemaster das Login des Spielleiters, der das Spiel leite t
* @return das Game-Objekt
Game-Objek
*/
public Game createGame(String name, String nicename, String gamemaster)
throws RemoteException
{
// Daten für das Spiel erzeugen
String chatroom = name;
String to_gm_place = gamemaster + "/to_" + name;
String from_gm_place = gamemaster + "/from_" + name;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "INSERT INTO games (name, nicename, chatroom,
to_gm_place, from_gm_place, gamemaster) values(";
query += Static.sqlString(name);
query += ", ";
query += Static.sqlString(nicename);
query += ", ";
query += Static.sqlString(chatroom);
query += ", ";
query += Static.sqlString(to_gm_place);
query += ", ";
query += Static.sqlString(from_gm_place);
query += ", ";
query += Static.sqlString(gamemaster);
query += ")";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return new Game(name, nicename, chatroom, to_gm_place, from_gm_place,
gamemaster);
}
/**
* Diese Methode löscht ein Spiel und alle teilnehmenden Gruppen .
*
* @param name der Name des Spiel s
*/
public void deleteGame(String name
name)
throws RemoteException
{
// game holen
Game game = getGame(name);
// verbindung zum fileserver holen
FileServer fs =
(FileServer)service_controller.getService(FILE_SERVER);
if(fs != null)
if
{
// Places löschen
fs.deletePlace(game.getToGameMasterPlace());
fs
fs.deletePlace(game.getFromGameMasterPlace());
fs
}
// Liste der Gruppen holen
Vector groups = listGroups(name);
// jede Gruppe löschen
Enumeration enum = groups.elements();
while(enum.hasMoreElements())
while
{
// Gruppe holen
Group group = (Group) enum.nextElement();
// Gruppe löschen
deleteGroup(group.getName(), name);
deleteGroup
}
// Nun noch die Gruppe aus der Datenbank löschen
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "DELETE FROM games WHERE name=" +
Static.sqlString(name);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Teilt einem Spiel einen neuen Spielleiter zu .
*
* @param game der Name des Spiel s
* @param gamemaster der Name des neuen Spielleiter s
*/
public void changeGameMaster(String game, String gamemaster)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE games SET gamemaster=" +
Static.sqlString(gamemaster) + "WHERE name=" + Static.sqlString(game);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Diese Methode sucht informationen zu einem Spiel und liefert e s
* zurück.
zurück
*
* @param name der Name des Spiel s
* @return das Game-Objekt oder null wenn das Spiel nicht existier t
*/
public Game getGame(String name)
throws RemoteException
{
Game result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT nicename, chatroom, to_gm_place,
from_gm_place, gamemaster FROM games WHERE name=";
query += Static.sqlString(name);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String nicename = rs.getString("nicename");
String chatroom = rs.getString("chatroom");
String to_gm_place = rs.getString("to_gm_place");
String from_gm_place = rs.getString("from_gm_place");
String gamemaster = rs.getString("gamemaster");
// Game erstellen
result = new Game(name, nicename, chatroom, to_gm_place,
from_gm_place, gamemaster);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Listet alle Spiele applikationsweit auf.
auf
*
* @return einen Vector der Game-Objekte enthält .
*/
public Vector listGames()
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, nicename, chatroom, to_gm_place,
from_gm_place, gamemaster FROM games ORDER BY games";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
while(rs.next())
while
{
String name = rs.getString("name");
String nicename = rs.getString("nicename");
String chatroom = rs.getString("chatroom");
String to_gm_place = rs.getString("to_gm_place");
String from_gm_place = rs.getString("from_gm_place");
String gamemaster = rs.getString("gamemaster");
// Game erstellen
Game game = new Game(name, nicename, chatroom, to_gm_place,
from_gm_place, gamemaster);
result.add(game);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Diese Methode erstellt eine Gruppe.
Gruppe
*
* @param name der Name der Grupp e
* @param nicename der Name der Gruppe wie er auf dem Bildschir m
dargestellt wird
wir
* @param game der Name des Spiels zu der die Gruppe gehör t
*/
public Group createGroup(String name, String nicename, String game)
throws RemoteException
{
String group_place = game + "/" + name;
String master_place = game + "/" + name + "to_gm";
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "INSERT INTO pgroups (name, nicename, game,
group_place, master_place) values(";
query += Static.sqlString(name);
query += ", ";
query += Static.sqlString(nicename);
query
query
query
query
query
query
query
+=
+=
+=
+=
+=
+=
+=
", ";
Static.sqlString(game);
", ";
Static.sqlString(group_place);
", ";
Static.sqlString(master_place);
")";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return new Group(name, nicename, game, group_place, master_place);
}
/**
* Diese Methode löscht eine Gruppe und all deren Mitspieler .
*
* @param name der Name der Grupp e
* @param game der Name des SPiels zu dem die Gruppe gehör t
*/
public void deleteGroup(String name, String game)
throws RemoteException
{
// gruppe holen
Group group = getGroup(name, game);
// verbindung zum fileserver holen
FileServer fs =
(FileServer)service_controller.getService(FILE_SERVER);
if
if(fs
!= null)
{
// Places löschen
fs.deletePlace(group.getGroupPlace());
fs
fs.deletePlace(group.getMasterPlace());
fs
}
// Mitspieler der Gruppe holen
Vector players = listPlayers(name, game);
Enumeration enum = players.elements();
while(enum.hasMoreElements())
while
{
Player player = (Player) enum.nextElement();
// Spieler löschen
deletePlayer(player.getLogin());
deletePlayer
}
// Gruppe aus der Datenbank löschen
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "DELETE FROM pgroups WHERE name=" +
Static.sqlString(name) + " AND game=" + Static.sqlString(game);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Diese Methode sucht Informationen zu einer Gruppe und liefert ei n
* Group-Objekt zurück.
zurück
*
* @param name der Name der Grupp e
* @param game der Name des Spiels zu dem die Gruppe gehör t
* @return null, wenn die Gruppe nicht gefunden wurde, sonst da s
Group-Objekt
Group-Objek
*/
public Group getGroup(String name, String game)
throws RemoteException
{
Group result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT nicename, group_place, master_place FROM
pgroups WHERE name=";
;
query += Static.sqlString(name) + " AND game=" +
Static.sqlString(game);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String nicename = rs.getString("nicename");
String group_place = rs.getString("group_place");
String master_place = rs.getString("master_place");
// Group anlegen
result = new Group(name, nicename, game, group_place,
master_place);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Listet alle Gruppen in einem Spiel auf .
*
* @param game das Spiel
Spie
* @return einen Vector, der Group-Objekte enthäl t
*/
public Vector listGroups(String game)
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, nicename, group_place, master_place
FROM pgroups WHERE game=";
;
query += Static.sqlString(game);
query += " ORDER BY name";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
while(rs.next())
while
{
String name = rs.getString("name");
String nicename = rs.getString("nicename");
String group_place = rs.getString("group_place");
String master_place = rs.getString("master_place");
// Group anlegen
Group group = new Group(name, nicename, game, group_place,
master_place);
result.addElement(group);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
;
}
/**
* Listet alle Gruppen applikationsweit auf.
auf
*
* @return einen Vector, der Group-Objekte enthäl t
*/
public Vector listGroups()
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, nicename, game, group_place,
master_place FROM pgroups ORDER BY name";
;
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
while(rs.next())
while
{
String name = rs.getString("name");
String nicename = rs.getString("nicename");
String game = rs.getString("game");
String group_place = rs.getString("group_place");
String master_place = rs.getString("master_place");
// Group anlegen
Group group = new Group(name, nicename, game, group_place,
master_place);
result.addElement(group);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
;
}
/**
* Diese Methode erstellt einen neuen Spieler.
*
* @param login der login des Spieler s
* @param name der Name des Spieler s
* @param email die E-Mail-Addresse des Spieler s
* @param group der Name der Gruppe zu der der Spieler gehör t
* @param game der Name des Spiels zu dem die Gruppe gehör t
* @param language das 2-Buchstaben-Kürzel der Sprache in der de r
Spieler die Webseiten anschaut
anschau
*/
public Player createPlayer(String login, String name, String email,
String group, String game, String language)
throws RemoteException
{
// Passwort generieren
StringBuffer password = new StringBuffer();
byte[] numbers = new byte[10];
byte
random.nextBytes(numbers);
random
int count = 0;
while
while(count
< 10)
{
// append the char representation of this number to the buffer
String number = (new Integer(numbers[count])).toString();
password.append(number.substring(number.length() - 1));
password
count++;
count
// Striche um die Zahl in Blöcke zu je 5 Zahlen zu Strukturieren
if(count == 5)
if
password.append("-");
password
}
// Name und Email des Game Masters
String gm_name = null;
String gm_email = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// erst mal schauen ob der login schon bei den spielleitern
existiert
String query = "SELECT login FROM gamemasters WHERE login=" +
Static.sqlString(login);
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(query);
if(rs.next())
if
{
s.close();
conn.close();
conn
return null;
}
s.close();
// Query zusammenbauen
query = "INSERT INTO players (login, password, name, pgroup,
language, game, email, first_login) values(";
query += Static.sqlString(login);
query += ", ";
query += Static.sqlString(password.toString());
query += ", ";
query += Static.sqlString(name);
query += ", ";
query += Static.sqlString(group);
query += ", ";
query += Static.sqlString(language);
query += ", ";
query += Static.sqlString(game);
query += ", ";
query += Static.sqlString(email);
query += ", 1)";
// Statement erstellen lassen
s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Namen und Email des Gamemasters herausfinden
query = "SELECT gamemasters.name AS gm_name, gamemasters.email AS
gm_email FROM gamemasters, games WHERE gamemasters.login=games.gamemaster
AND games.name=" + Static.sqlString(game);
s = conn.createStatement();
rs = s.executeQuery(query);
if(rs.next())
if
{
gm_name = rs.getString("gm_name");
gm_email = rs.getString("gm_email");
}
s.close();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
// passwort per mail an den spieler schicken
Properties strings = new Properties();
strings.put("password", password);
strings
strings.put("gm_email", gm_email);
strings
strings.put("gm_name", gm_name);
strings
sendPlayerMail(gm_email, gm_name, login, "newplayer-" + language,
sendPlayerMail
strings);
return new Player(login, name, group, game, email, language, true);
}
/**
* Diese Methode ändert das Passwort eines Spielers .
*
* @param login der Login des Spieler s
* @param password das neue Passwort des Spieler s
*/
public void changePlayerPassword(String login, String password)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE players SET password=" +
Static.sqlString(password) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Diese Methode ändert die Sprache eines Spielers .
*
* @param login der Login des Spieler s
* @param language die neue Sprache des Spieler s
*/
public void changePlayerLanguage(String login, String language)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE players SET language=" +
Static.sqlString(language) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Ändert die Email-Addresse eines Spielers.
Spielers
*
* @param login der Login des Spieler s
* @param email die neue Email des Spieler s
*/
public void changePlayerEmail(String login, String email)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE players SET email=" +
Static.sqlString(email) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Löscht einen Spieler.
Spieler
*
* @param login der login des Spielers .
*/
public void deletePlayer(String login)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "DELETE FROM players WHERE login=" +
Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Sucht informationen über einen Spieler und liefert sie in Form eine s
* Player-Objektes zurück.
zurück
*
* @param login der login des Spieler s
*/
public Player getPlayer(String login)
throws RemoteException
{
Player result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, pgroup, language, game, email,
first_login FROM players WHERE login=";
query += Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String name = rs.getString("name");
String group = rs.getString("group");
String language = rs.getString("language");
String game = rs.getString("game");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
// Player erzeugen
result = new Player(login, name, group, game, email, language,
first_login == 1);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Listet alle Spieler einer Gruppe auf .
*
* @param group die Gruppe
Grupp
* @param game das Spiel
Spie
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers(String group, String game)
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT login, name, language, email, first_login
FROM players WHERE game=";
query += Static.sqlString(game) + " AND pgroup=" +
Static.sqlString(group);
query += " ORDER BY login";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String login = rs.getString("login");
String name = rs.getString("name");
String language = rs.getString("language");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
// Player erzeugen
Player player = new Player(login, name, group, game, email,
language, first_login == 1);
result.addElement(player);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
;
}
/**
* Listet alle Spieler eines Spiels auf .
*
* @param game das Spiel
Spie
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers(String game)
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT login, name, pgroup, language, email,
first_login FROM players WHERE game=";
query += Static.sqlString(game);
query += " ORDER BY login";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String login = rs.getString("login");
String name = rs.getString("name");
String group = rs.getString("pgroup");
String language = rs.getString("language");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
// Player erzeugen
Player player = new Player(login, name, group, game, email,
language, first_login == 1);
result.addElement(player);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
;
}
/**
* Listet alle Spieler applikationsweit auf.
auf
*
* @return einen Vector mit Player-Objekten
Player-Objekte
*/
public Vector listPlayers()
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT login, name, pgroup, game, language, email,
first_login FROM players ";
query += " ORDER BY login";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
if(rs.next())
if
{
String login = rs.getString("login");
String name = rs.getString("name");
String group = rs.getString("pgroup");
String game = rs.getString("game");
String language = rs.getString("language");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
// Player erzeugen
Player player = new Player(login, name, group, game, email,
language, first_login == 1);
result.addElement(player);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
;
}
/**
* Fügt einen GameMaster hinzu
hinz
*
* @param login der Login des neuen GameMaster s
* @param email die Email des neuen GameMaster s
* @param name der Name des neuen GameMaster s
* @param language die Sprache des neuen Spielleiter s
* @return den neuen GameMaster oder nul l
*/
public GameMaster createGameMaster(String login, String email, String
name, String language)
throws RemoteException
{
// Passwort generieren
StringBuffer password = new StringBuffer();
byte[] numbers = new byte[10];
byte
random.nextBytes(numbers);
random
int count = 0;
while
while(count
< 10)
{
// append the char representation of this number to the buffer
String number = (new Integer(numbers[count])).toString();
password.append(number.substring(number.length() - 1));
password
count++;
count
// Striche um die Zahl in Blöcke zu je 5 Zahlen zu Strukturieren
if(count == 5)
if
password.append("-");
password
}
try
{
// Connection holen
Connection conn = pool.getConnection();
// erst mal schauen ob der login schon bei den spielleitern
existiert
String query = "SELECT login FROM players WHERE login=" +
Static.sqlString(login);
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(query);
if(rs.next())
if
{
s.close();
conn.close();
conn
return null;
}
s.close();
// Query zusammenbauen
query = "INSERT INTO gamemasters (login, password, name, email,
first_login, language) values(";
query += Static.sqlString(login);
query += ", ";
query += Static.sqlString(password.toString());
query += ", ";
query += Static.sqlString(name);
query += ", ";
query += Static.sqlString(email);
query += ",1 , ";
query += Static.sqlString(language);
query += ")";
// Statement erstellen lassen
s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return new GameMaster(login, name, email, language, true);
);
}
/**
* Löscht einen GameMaster
GameMaste
*
* @param login der Login des GameMasters der gelöscht werden sol l
*/
public void deleteGameMaster(String login)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "DELETE FROM gamemasters WHERE login=" +
Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Generiert eine Liste der GameMasters
GameMaster
*
* @return einen Vector mit GameMaster-Objekten
GameMaster-Objekte
*/
public Vector listGameMasters()
throws RemoteException
{
Vector result = new Vector();
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT login, name, email, first_login, language
FROM gamemasters";
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
// ResultSet auslesen
while(rs.next())
while
{
String login = rs.getString("login");
String name = rs.getString("name");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
String language = rs.getString("language");
//
GameMaster game_master = new GameMaster(login, name, email,
language, first_login==1);
result.addElement(game_master);
result
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Ändert das Passwort eines Spielleiters.
Spielleiters
*
* @param login der Login des Spielleiter s
* @param password das neue Passwort des Spielleiter s
*/
public void changeGameMasterPassword(String login, String password)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE gamemasters SET password=" +
Static.sqlString(password) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Ändert die Email Adresse eines Spielleiters .
*
* @param login der Login des Spielleiter s
* @param email die neue Email des Spielleiter s
*/
public void changeGameMasterEmail(String login, String email)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE gamemasters SET email=" +
Static.sqlString(email) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Ändert die Sprache eines Spielleiters.
Spielleiters
*
* @param login der Login des Spielleiter s
* @param language die neue Sprache des Spielleiter s
*/
public void changeGameMasterLanguage(String login, String language)
throws RemoteException
{
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "UPDATE gamemasters SET language=" +
Static.sqlString(language) + "WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
s.execute(query);
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Liest einen Spielleiter aus der Datenban k
*
* @param login der Login des SPielleiter s
* @return den Spielleiter
Spielleite
*/
public GameMaster getGameMaster(String login)
throws RemoteException
{
GameMaster result = null;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT name, email, first_login, language FROM
gamemasters WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
if(rs.next())
if
{
String name = rs.getString("name");
String email = rs.getString("email");
int first_login = rs.getInt("first_login");
String language = rs.getString("language");
result = new GameMaster(login, name, email, language,
first_login == 1);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
return result;
}
/**
* Verschickt ein Mail Template an alle Mitglieder eines Spiel s
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param game der Name des Spiels
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGameMail(String snd_email, String snd_name, String game,
String template, Hashtable strings)
throws RemoteException
{
// Liste der Spieler holen
Vector players = listPlayers(game);
Enumeration enum = players.elements();
while(enum.hasMoreElements())
while
{
Player player = (Player) enum.nextElement();
sendPlayerMail(snd_email, snd_name, player.getLogin(), template,
sendPlayerMail
strings);
}
// Auch den Spielleiter mit einer Mail versehen
Game the_game = getGame(game);
GameMaster game_master = getGameMaster(the_game.getGameMaster());
sendGameMasterMail(snd_email, snd_name, game_master.getLogin(),
sendGameMasterMail
template, strings);
}
/**
* Verschickt ein Mail Template an alle Mitlieder einer Grupp e
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param game der Name des Spiels
* @param group der Name der Gruppe
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGroupMail(String snd_email, String snd_name, String
game, String group, String template, Hashtable strings)
throws RemoteException
{
// Liste der Spieler holen
Vector players = listPlayers(game, group);
Enumeration enum = players.elements();
while(enum.hasMoreElements())
while
{
Player player = (Player) enum.nextElement();
sendPlayerMail(snd_email, snd_name, player.getLogin(), template,
sendPlayerMail
strings);
}
}
/**
* Verschickt ein Mail Template an einen Spiele r
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param login Login des Spielers
Spieler
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendPlayerMail(String snd_email, String snd_name, String
login, String template, Hashtable strings)
throws RemoteException
{
Player player = getPlayer(login);
MailServer ms =
(MailServer)service_controller.getService(MAIL_SERVER);
if(ms != null)
if
ms.sendTemplate(template + "-" + player.getLanguage(), snd_email,
ms
snd_name, player.getEmail(), player.getName(), strings);
}
/**
* Verschickt ein Mail Template an einen SpielLeite r
*
* @param snd_email der Absender der emai l
* @param snd_name der Name des Absender s
* @param login Login des SpielLeiters
SpielLeiter
* @param template das Template das geschickt werden sol l
* @param strings Werte die in die Mail geparst werden sollen oder nul l
wenn
*
keine Werte geparst werden solle n
*/
public void sendGameMasterMail(String snd_email, String snd_name, String
login, String template, Hashtable strings)
throws RemoteException
{
GameMaster game_master = getGameMaster(login);
MailServer ms =
(MailServer)service_controller.getService(MAIL_SERVER);
if(ms != null)
if
ms.sendTemplate(template + "-" + game_master.getLanguage(),
ms
snd_email, snd_name, game_master.getEmail(), game_master.getName(),
strings);
}
/**
* Verschickt eine Mail an einen Spielleiter oder Spieler und teilt ih m
sein Passwort mit.
mit
*
* @param login der Login des Spielleiters oder Spieler s
*/
public void sendPasswordMail(String login)
throws RemoteException
{
boolean found = false;
try
{
// Connection holen
Connection conn = pool.getConnection();
// Query zusammenbauen
String query = "SELECT password, email, name, language FROM
players WHERE login=" + Static.sqlString(login);
// Statement erstellen lassen
Statement s = conn.createStatement();
// Query machen
ResultSet rs = s.executeQuery(query);
if(rs.next())
if
{
String password = rs.getString("password");
String email = rs.getString("email");
String name = rs.getString("name");
String language = rs.getString("language");
// found auf true setzen
found = true;
// mail verschicken
Hashtable strings = new Hashtable();
strings.put("password", password);
strings
sendPlayerMail(WEBMASTER_EMAIL, WEBMASTER_NAME, login,
sendPlayerMail
"forgotpassword-" + language, strings);
}
// Statement schliessen
s.close();
();
// Connection zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error while using database", sql);
}
}
/**
* Diese Methode wird vom Join Manager aufgerufen um dem Service sein e
Service ID mitzuteilen
mitzuteile
* so bald der Service registriert ist .
*
* @param service_id Service ID
I
*/
public void serviceIDNotify(ServiceID service_id)
{
System.out.print("Service registered, ID: ");
System
System.out.println(service_id);
System
}
/**
* Gibt true zurück wenn alles mit dem FileServer in Ordnung ist .
*
* @return true wenn alles mit dem FileServer in Ordnung ist .
*/
public boolean isAlive()
throws RemoteException
{
// check the database connection
try
{
// kleine Testquery
Connection conn = pool.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT checkvalue FROM
checktable");
if(rs.next())
if
{
String weltherrschaft = rs.getString("checkvalue");
if(weltherrschaft == null ||
if
!weltherrschaft.equalsIgnoreCase("WELTHERRSCHAFT"))
return false;
}
else
return false;
s.close();
conn.close();
conn
}
catch(SQLException sql)
catch
{
return false;
}
return true;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.Group
java.lang.Object
|
+----mm.services.game.Group
public class Group
extends java.lang.Object
implements java.io.Serializable
Diese Klasse speichert alle Informationen zu einer Gruppe wie Name der
gruppen- internen Fileplaces, Messageboards und Chatrooms.
Version:
1.0
Author:
Stefan Zier
Group(String, String, String, String, String)
Dieser Konstruktor generiert das Objekt.
getGame()
Liefert das Spiel zu dem die Gruppe gehört.
getGroupPlace()
Liefert den Place auf dem die Gruppe untereinander Daten austauscht
getMasterPlace()
Liefert den Place mit dem die Gruppe Daten mit dem Spielleiter
austauscht
getName()
Liefert den Namen der Gruppe.
getNiceName()
Liefert den Namen der Gruppe zur Darstellung auf dem Bildschirm
Group
public Group(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
name,
nicename,
game,
group_place,
master_place)
Dieser Konstruktor generiert das Objekt. Alle informationen werden
hier an die Klasse übergeben.
Parameters:
name - der Name der Gruppe
nicename - der Name der Gruppe zur Darstellung auf dem
Bildschirm
game - das Spiel zu dem die Gruppe gehört
group_place - der File-place, der zur Gruppe gehört
master_place - der File-place mit dem die Gruppe Dateien mit dem
Spielleiter austauscht
getName
public java.lang.String getName()
Liefert den Namen der Gruppe.
Returns:
den Namen der Gruppe.
getNiceName
public java.lang.String getNiceName()
Liefert den Namen der Gruppe zur Darstellung auf dem Bildschirm
Returns:
den Namen der Gruppe zur Darstellung auf dem Bildschirm
getGame
public java.lang.String getGame()
Liefert das Spiel zu dem die Gruppe gehört.
Returns:
das Spiel zu dem die Gruppe gehört.
getGroupPlace
public java.lang.String getGroupPlace()
Liefert den Place auf dem die Gruppe untereinander Daten
austauscht
Returns:
den Place auf dem die Gruppe untereinander Daten austauscht
getMasterPlace
public java.lang.String getMasterPlace()
Liefert den Place mit dem die Gruppe Daten mit dem Spielleiter
austauscht
Returns:
den Place mit dem die Gruppe Daten mit dem Spielleiter
austauscht
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
import java.io.Serializable;
/**
* Diese Klasse speichert alle Informationen zu einer Gruppe wie Name de r
gruppengruppen
* internen Fileplaces, Messageboards und Chatrooms.
Chatrooms
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Group implements Serializable
{
private String name = null;
private String nicename = null;
private String game = null;
private String group_place = null;
private String master_place = null;
/**
* Dieser Konstruktor generiert das Objekt. Alle informationen werde n
hier
* an die Klasse übergeben.
übergeben
*
* @param name der Name der Grupp e
* @param nicename der Name der Gruppe zur Darstellung auf de m
Bildschirm
Bildschir
* @param game das Spiel zu dem die Gruppe gehör t
* @param group_place der File-place, der zur Gruppe gehör t
* @param master_place der File-place mit dem die Gruppe Dateien mit de m
*
Spielleiter austauscht
austausch
*/
public Group(String name, String nicename, String game, String
group_place, String master_place)
{
this.name = name;
this
this.nicename = nicename;
this
this.game = game;
this
this.group_place = group_place;
this
this.master_place = master_place;
this
}
/**
* Liefert den Namen der Gruppe.
Gruppe
*
* @return den Namen der Gruppe.
Gruppe
*/
public String getName()
{
return name;
}
/**
* Liefert den Namen der Gruppe zur Darstellung auf dem Bildschir m
*
* @return den Namen der Gruppe zur Darstellung auf dem Bildschir m
*/
public String getNiceName()
{
return nicename;
}
/**
* Liefert das Spiel zu dem die Gruppe gehört .
*
* @return das Spiel zu dem die Gruppe gehört .
*/
public String getGame()
{
return game;
}
/**
* Liefert den Place auf dem die Gruppe untereinander Daten austausch t
*
* @return den Place auf dem die Gruppe untereinander Daten austausch t
*/
public String getGroupPlace()
{
return group_place;
}
/**
* Liefert den Place mit dem die Gruppe Daten mit dem Spielleite r
austauscht
austausch
*
* @return den Place mit dem die Gruppe Daten mit dem Spielleite r
austauscht
austausch
*/
public String getMasterPlace()
{
return master_place;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.Player
java.lang.Object
|
+----mm.services.game.Player
public class Player
extends java.lang.Object
implements java.io.Serializable
Diese Klasse enthält alle Informationen über einen Mitspieler des
Planspiels. Sie wird vom Spielserver verwaltet. Der Webserver greift darauf
über RMI zu.
Version:
1.0
Author:
Stefan Zier
Player(String, String, String, String, String, String, boolean)
Konstruktor.
getEmail()
Accessor für
getGame()
Accessor für
getGroup()
Accessor für
getLanguage()
Accessor für
getLogin()
Accessor für
getName()
Accessor für
isFirstLogin()
Accessor für
email.
das Spiel
die Gruppe
Sprache.
Login
den Namen
First Login.
Player
public Player(java.lang.String login,
java.lang.String name,
java.lang.String group,
java.lang.String game,
java.lang.String email,
java.lang.String language,
boolean first_login)
Konstruktor.
Parameters:
login - der Login des Spielers
name - der Name des Spielers
group - die Gruppe zu der der Spieler gehört
game - das Spiel an dem der Spieler teilnimmt
email - die Email-Addresse des Spielers
language - die Sprache in der der Spieler die Webseiten betrachten
will
getLogin
public java.lang.String getLogin()
Accessor für Login
Returns:
den Login des Spielers
getName
public java.lang.String getName()
Accessor für den Namen
Returns:
den Namen des Spielers
getGroup
public java.lang.String getGroup()
Accessor für die Gruppe
Returns:
die Gruppe des Spielers
getGame
public java.lang.String getGame()
Accessor für das Spiel
Returns:
den Namen des Spiels an dem der Spieler teilnimmt
getEmail
public java.lang.String getEmail()
Accessor für email.
Returns:
die Email Adresse des Spielers
getLanguage
public java.lang.String getLanguage()
Accessor für Sprache.
Returns:
die Sprache in der der Spieler die Webseiten betrachten will.
isFirstLogin
public boolean isFirstLogin()
Accessor für First Login.
Returns:
true wenn sich der Spieler zum ersten mal einloggt.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
import java.io.Serializable;
/**
* Diese Klasse enthält alle Informationen über einen Mitspieler de s
Planspiels.
Planspiels
* Sie wird vom Spielserver verwaltet. Der Webserver greift darauf über RM I
zu.
zu
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Player implements Serializable
{
private String login = null;
private String name = null;
private String group = null;
private String game = null;
private String email = null;
private String language = null;
private boolean first_login;
/**
* Konstruktor.
Konstruktor
*
* @param login der Login des Spieler s
* @param name der Name des Spieler s
* @param group die Gruppe zu der der Spieler gehör t
* @param game das Spiel an dem der Spieler teilnimm t
* @param email die Email-Addresse des Spieler s
* @param language die Sprache in der der Spieler die Webseite n
betrachten will
wil
* @paran first_login wahr wenn sich der Spieler zum ersten ma l
eingeloggt hat
ha
*/
public Player(String login, String name, String group, String game,
String email, String language, boolean first_login)
{
this.login = login;
this
this.name = name;
this
this.group = group;
this
this.game = game;
this
this.email = email;
this
this.language = language;
this
this.first_login = first_login;
this
}
/**
* Accessor für Login
Logi
*
* @return den Login des Spielers
Spieler
*/
public String getLogin()
{
return login;
}
/**
* Accessor für den Namen
Name
*
* @return den Namen des Spielers
Spieler
*/
public String getName()
{
return name;
}
/**
* Accessor für die Gruppe
Grupp
*
* @return die Gruppe des Spielers
Spieler
*/
public String getGroup()
{
return group;
}
/**
* Accessor für das Spiel
Spie
*
* @return den Namen des Spiels an dem der Spieler teilnimm t
*/
public String getGame()
{
return game;
}
/**
* Accessor für email.
email
*
* @return die Email Adresse des Spieler s
*/
public String getEmail()
{
return email;
}
/**
* Accessor für Sprache.
Sprache
*
* @return die Sprache in der der Spieler die Webseiten betrachten will .
*/
public String getLanguage()
{
return language;
}
/**
* Accessor für First Login.
Login
*
* @return true wenn sich der Spieler zum ersten mal einloggt .
*/
public boolean isFirstLogin()
{
return first_login;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.game.RegisterGameServer
java.lang.Object
|
+----mm.services.game.RegisterGameServer
public class RegisterGameServer
extends java.lang.Object
Diese Klasse instantiiert den Game server und registriert ihn beim Lookup
Service.
Version:
1.0
Author:
Stefan Zier
RegisterGameServer()
main(String[])
Main methode.
RegisterGameServer
public RegisterGameServer()
main
public static void main(java.lang.String argsv[])
Main methode.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.game;
// Java core imports
import java.rmi.*;
// Jini extension imports
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.lookup.entry.Name;
import net.jini.lookup.entry.ServiceInfo;
import net.jini.core.entry.Entry;
/**
* Diese Klasse instantiiert den Game server und registriert ihn bei m
Lookup Service.
Service
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class RegisterGameServer
{
static JoinManager jm;
static GameServerImpl gameserver_instance;
/**
* Main methode.
*/
public static void main(String[] argsv)
{
System.out.println("RegisterGameServer (c) 1999 MM Jahresprojekt");
System
try
{
// install security manager so that we'll be able to talk to
server
System.out.println(">> installiere RMI Security manager...");
System
System.setSecurityManager(new RMISecurityManager());
System
// create service
System.out.println(">> instantiiere Game Server ...");
System
gameserver_instance = new GameServerImpl();
// this name will be seen to users that browse services
Name nameEntry = new Name("MM Game Server");
// some addtl. serivice information such as manufacterer etc.
ServiceInfo serviceInfo = new ServiceInfo("MM Game Server", "CE5
WS 1999/2000",
"CE5 WS 1999/2000", "1.0", "", "");
// gather all information that we're going to pass on to the
lookup service
Entry entries[] = new Entry[] {nameEntry, serviceInfo};
System.out.println(">> registriere den Game Server beim Lookup
System
Service...");
// create a new join manager and have it register the
jts_instance.
jm = new JoinManager(gameserver_instance, entries,
(ServiceIDListener) gameserver_instance, new LeaseRenewalManager());
System.out.println(">> Game Server bereit");
System
}
catch(Exception e)
catch
{
System.out.println("##### mm: exception caught: ");
System
e.printStackTrace();
}
}
}
e.) mm.services.mailer
Dieses Package enthält Klassen des Mailer-Dienstes.
Klasse
MailServer
MailServerImpl
RegisterMailServer
Bedeutung
Das Remote-Interface des Mailer-Dienstes
Die Implementation des Mailer-Dienstes
Instantiiert einen Spielmanager-Dienst und
registriert ihn beim Lookup Service
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface mm.services.mailer.MailServer
public interface MailServer
extends java.rmi.Remote, AliveCheckable
Dies ist das Interface zu einem Mailserver der Mails verschicken kann.
Version:
1.0
Author:
Stefan Zier
sendMail(String, String, String, String, String, String)
Versendet eine Mail.
sendTemplate(String, String, String, String, String, Hashtable)
Versendet ein Mail Template aus der Datenbank.
sendMail
public void sendMail(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
snd_email,
snd_name,
rcp_email,
rcp_name,
subject,
body) throws java.rmi.RemoteException
Versendet eine Mail.
Parameters:
snd_email - die email-addresse des absenders
snd_name - der name des absenders
rcp_email - die email-addresse des empfängers
rcp_name - der name des empfängers
subject - das Subject der email
body - der Körper der email
sendTemplate
public void sendTemplate(java.lang.String template,
java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String rcp_email,
java.lang.String rcp_name,
java.util.Hashtable strings) throws java.rmi.RemoteException
Versendet ein Mail Template aus der Datenbank.
Parameters:
template - der Namen des Templates
snd_email - die email-addresse des absenders
snd_name - der name des absenders
rcp_email - die email-addresse des empfängers
rcp_name - der name des empfängers
strings - Strings die in dem Template in der Form angegeben
werden können. In der Hashtable müssen Wertepaare in mit
tagname als Schlüssel und dem Wert der an Stelle des Tags
eingesetzt werden soll stehen. Vordefinierte Tags sind: die Email
des Absenders der Name des Absenders die Email des Empfängers
der Name des Empfängers
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.mailer;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Hashtable;
import mm.tools.AliveCheckable;
/**
* Dies ist das Interface zu einem Mailserver der Mails verschicken kann .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public interface MailServer extends Remote, AliveCheckable
{
/**
* Versendet eine Mail.
*
* @param snd_email die email-addresse des absender s
* @param snd_name der name des absender s
* @param rcp_email die email-addresse des empfänger s
* @param rcp_name der name des empfänger s
* @param subject das Subject der emai l
* @param body der Körper der emai l
*/
public void sendMail(String snd_email, String snd_name,
String rcp_email, String rcp_name,
String subject, String body)
throws RemoteException;
/**
* Versendet ein Mail Template aus der Datenbank .
*
* @param template der Namen des Template s
* @param snd_email die email-addresse des absender s
* @param snd_name der name des absender s
* @param rcp_email die email-addresse des empfänger s
* @param rcp_name der name des empfänger s
* @param strings Strings die in dem Template in der Form <tagname >
*
angegeben werden können. In der Hashtable müssen Wertepaare i n
*
mit tagname als Schlüssel und dem Wert der an Stelle des Tag s
*
eingesetzt werden soll stehen. Vordefinierte Tags sind :
*
<snd_email> die Email des Absender s
*
<snd_name> der Name des Absender s
*
<rcp_email> die Email des Empfänger s
*
<rcp_name> der Name des Empfänger s
*/
public void sendTemplate(String template, String snd_email, String
snd_name,
String rcp_email, String rcp_name,
Hashtable strings)
throws RemoteException;
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.mailer.MailServerImpl
mm.services.mailer.MailServerImpl
public class MailServerImpl
implements MailServer
Dies ist die Implementation des Mail Servers. Er benutzt die Mail API von
Sun.
Version:
1.0
Author:
Stefan Zier
MailServerImpl()
Konstruktor.
isAlive()
Liefert true wenn alles in Ordnung ist mit dem Mailserver.
sendMail(String, String, String, String, String, String)
Versendet eine Mail.
sendTemplate(String, String, String, String, String, Hashtable)
Versendet ein Mail Template aus der Datenbank.
serviceIDNotify(ServiceID)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
MailServerImpl
public MailServerImpl() throws java.rmi.RemoteException, java.io.IOException, java.sql.SQL
Konstruktor. Liest die Konfigurationsdatei mailserver.properties und
bereitet den Versand der Mails vor.
sendMail
public void sendMail(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
snd_email,
snd_name,
rcp_email,
rcp_name,
subject,
body) throws java.rmi.RemoteException
Versendet eine Mail.
Parameters:
snd_email - die email-addresse des absenders
snd_name - der name des absenders
rcp_email - die email-addresse des empfängers
rcp_name - der name des empfängers
subject - das Subject der email
body - der Körper der email
sendTemplate
public void sendTemplate(java.lang.String template,
java.lang.String snd_email,
java.lang.String snd_name,
java.lang.String rcp_email,
java.lang.String rcp_name,
java.util.Hashtable strings) throws java.rmi.RemoteException
Versendet ein Mail Template aus der Datenbank.
Parameters:
template - der Namen des Templates
snd_email - die email-addresse des absenders
snd_name - der name des absenders
rcp_email - die email-addresse des empfängers
rcp_name - der name des empfängers
strings - Strings die in dem Template in der Form angegeben
werden können. In der Hashtable müssen Wertepaare in mit
tagname als Schlüssel und dem Wert der an Stelle des Tags
eingesetzt werden soll stehen. Vordefinierte Tags sind: die Email
des Absenders der Name des Absenders die Email des Empfängers
der Name des Empfängers
isAlive
public boolean isAlive() throws java.rmi.RemoteException
Liefert true wenn alles in Ordnung ist mit dem Mailserver.
Returns:
true wenn alles in Ordnung ist mit dem Mailserver.
serviceIDNotify
public void serviceIDNotify(net.jini.core.lookup.ServiceID service_id)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
Parameters:
service_id - Service ID
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.mailer;
// Java Core imports
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.io.IOException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.util.Properties;
import java.util.Hashtable;
import java.util.Enumeration;
// Database connection imports
import com.bitmechanic.sql.ConnectionPoolManager;
import com.bitmechanic.sql.ConnectionPool;
// Mail extensions imports
import javax.mail.Session;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.AddressException;
// Jini extension imports
import com.sun.jini.lookup.ServiceIDListener;
import net.jini.core.lookup.ServiceID;
// MM imports
import mm.tools.Static;
import mm.tools.ConfigFile;
/**
* Dies ist die Implementation des Mail Servers. Er benutzt die Mail AP I
von Sun.
Sun
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class MailServerImpl extends UnicastRemoteObject implements
MailServer, ServiceIDListener
{
// database connections
private ConnectionPoolManager cpm = null;
private ConnectionPool pool = null;
// mail session
private javax.mail.Session mail_session = null;
/**
* Konstruktor. Liest die Konfigurationsdatei mailserver.properties un d
bereitet den
de
* Versand der Mails vor.
vor
*/
public MailServerImpl()
throws RemoteException, IOException, SQLException,
ClassNotFoundException, InstantiationException, IllegalAccessException
{
// Konstruktor von UnicastRemoteObject aufrufen
super();
super
// Mailserver aus der Konfigurationsdatei lesen
ConfigFile configfile = new
ConfigFile("F:/mm/services/mailer/mailserver.properties");
String smtp = configfile.get("mailserver.smtp");
if(Static.empty(smtp))
if
throw new IllegalArgumentException("mm: the mailserver has not
been specified");
// Properties für die Mailsession festlegen
Properties mail_props = new Properties();
mail_props.put("mail.smtp.host", smtp);
mail_props
// Mail session anlegen
mail_session = javax.mail.Session.getInstance(mail_props, null);
// create a connection pool manager
cpm = new ConnectionPoolManager(120);
// get
String
String
String
url, username and password from the configuration file
url = configfile.get("mailserver.database.URL");
username = configfile.get("mailserver.database.username");
password = configfile.get("mailserver.database.password");
if
if(url
== null || url.equals(""))
{
throw new IllegalArgumentException("mm: no database URL given");
}
if(username == null || username.equals(""))
if
{
throw new IllegalArgumentException("mm: no database login given");
}
if(password == null || password.equals(""))
if
{
throw new IllegalArgumentException("mm: no database password
given");
}
// add the alias for "our" database
cpm.addAlias("mailserver", "org.gjt.mm.mysql.Driver", url, username,
cpm
password, 120, 300, 120);
pool = cpm.getPool("mailserver");
}
/**
* Versendet eine Mail.
*
* @param snd_email die email-addresse des absender s
* @param snd_name der name des absender s
* @param rcp_email die email-addresse des empfänger s
* @param rcp_name der name des empfänger s
* @param subject das Subject der emai l
* @param body der Körper der emai l
*/
public void sendMail(String snd_email, String snd_name,
String rcp_email, String rcp_name,
String subject, String body)
throws RemoteException
{
// neue Mail erzeugen
Message msg = new MimeMessage(mail_session);
// Empfängeraddressen in richtige Form bringen
InternetAddress[] rcps = new InternetAddress[1];
InternetAddress
try
{
rcps[0] = new InternetAddress(rcp_email);
rcps
}
catch(AddressException a)
catch
{
throw new RemoteException("mm: invalid recipient mail address",
a);
}
try
{
// empfänger festlegen
msg.setRecipients(Message.RecipientType.TO, rcps);
msg
// absender festlegen
msg.setFrom(new InternetAddress(snd_email));
msg
// subject festlegen
msg.setSubject(subject);
msg
// body festlegen
msg.setText(body);
msg
}
catch(MessagingException me)
catch
{
throw new RemoteException("mm: error setting email data", me);
}
try
{
Transport.send(msg);
Transport
}
catch(MessagingException me)
catch
{
throw new RemoteException("mm: error sending email", me);
}
}
/**
* Versendet ein Mail Template aus der Datenbank .
*
* @param template der Namen des Template s
* @param snd_email die email-addresse des absender s
* @param snd_name der name des absender s
* @param rcp_email die email-addresse des empfänger s
* @param rcp_name der name des empfänger s
* @param strings Strings die in dem Template in der Form <tagname >
*
angegeben werden können. In der Hashtable müssen Wertepaare i n
*
mit tagname als Schlüssel und dem Wert der an Stelle des Tag s
*
eingesetzt werden soll stehen. Vordefinierte Tags sind :
*
<snd_email> die Email des Absender s
*
<snd_name> der Name des Absender s
*
<rcp_email> die Email des Empfänger s
*
<rcp_name> der Name des Empfänger s
*/
public void sendTemplate(String template, String snd_email, String
snd_name,
String rcp_email, String rcp_name,
Hashtable strings)
throws RemoteException
{
try
{
// conn holen
Connection conn = pool.getConnection();
// query bauen
String query="SELECT subject, body FROM mail_templates WHERE
template=" + Static.sqlString(template);
// query machen
Statement sGetTemplate = conn.createStatement();
ResultSet rsGetTemplate = sGetTemplate.executeQuery(query);
if(rsGetTemplate.next())
if
{
// record auslesen
String subject = rsGetTemplate.getString("template");
String body = rsGetTemplate.getString("body");
// Standardvariablen parsen
subject = Static.replace(subject,
subject = Static.replace(subject,
subject = Static.replace(subject,
subject = Static.replace(subject,
body
body
body
body
=
=
=
=
Static.replace(body,
Static.replace(body,
Static.replace(body,
Static.replace(body,
"<snd_email>", snd_email);
"<snd_name>", snd_name);
"<rcp_email>", rcp_email);
"<rcp_name>", rcp_name);
"<snd_email>", snd_email);
"<snd_name>", snd_name);
"<rcp_email>", rcp_email);
"<rcp_name>", rcp_name);
// hashtable durchlaufen und alles parsen
Enumeration enum = strings.keys();
while(enum.hasMoreElements())
while
{
// Key aus der enumeration holen
String key = (String) enum.nextElement();
// value aus der Hashtable lesen
String value = (String) strings.get(key);
// replace in subject und body machen
subject = Static.replace(subject, "<" + key + ">", value);
body = Static.replace(body, "<" + key + ">", value);
}
// so, nun die mail wegschicken
sendMail(snd_email, snd_name, rcp_email, rcp_name, subject,
sendMail
body);
}
else
throw new RemoteException("mm: template not found in
database");
sGetTemplate.close();
sGetTemplate
// conn zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error reading mail template from
database", sql);
}
}
/**
* Liefert true wenn alles in Ordnung ist mit dem Mailserver .
*
* @return true wenn alles in Ordnung ist mit dem Mailserver .
*/
public boolean isAlive()
throws RemoteException
{
return true;
}
/**
* Diese Methode wird vom Join Manager aufgerufen um dem Service sein e
Service ID mitzuteilen
mitzuteile
* so bald der Service registriert ist .
*
* @param service_id Service ID
I
*/
public void serviceIDNotify(ServiceID service_id)
{
System.out.print("Service registered, ID: ");
System
System.out.println(service_id);
System
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.mailer.RegisterMailServer
java.lang.Object
|
+----mm.services.mailer.RegisterMailServer
public class RegisterMailServer
extends java.lang.Object
Diese Klasse instantiiert den Mail server und registriert ihn beim Lookup
Service.
Version:
1.0
Author:
Stefan Zier
RegisterMailServer()
main(String[])
Main methode.
RegisterMailServer
public RegisterMailServer()
main
public static void main(java.lang.String argsv[])
Main methode.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.mailer;
// Java core imports
import java.rmi.*;
// Jini extension imports
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.lookup.entry.Name;
import net.jini.lookup.entry.ServiceInfo;
import net.jini.core.entry.Entry;
/**
* Diese Klasse instantiiert den Mail server und registriert ihn bei m
Lookup Service.
Service
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class RegisterMailServer
{
static JoinManager jm;
static MailServerImpl mailserver_instance;
/**
* Main methode.
*/
public static void main(String[] argsv)
{
System.out.println("RegisterMailServer (c) 1999 MM Jahresprojekt");
System
try
{
// install security manager so that we'll be able to talk to
server
System.out.println(">> installiere RMI Security manager...");
System
System.setSecurityManager(new RMISecurityManager());
System
// create service
System.out.println(">> instantiiere Mail Server ...");
System
mailserver_instance = new MailServerImpl();
// this name will be seen to users that browse services
Name nameEntry = new Name("MM Mail Server");
// some addtl. serivice information such as manufacterer etc.
ServiceInfo serviceInfo = new ServiceInfo("MM Mail Server", "CE5
WS 1999/2000",
"CE5 WS 1999/2000", "1.0", "", "");
// gather all information that we're going to pass on to the
lookup service
Entry entries[] = new Entry[] {nameEntry, serviceInfo};
System.out.println(">> registriere den Mail Server beim Lookup
System
Service...");
// create a new join manager and have it register the
jts_instance.
jm = new JoinManager(mailserver_instance, entries,
(ServiceIDListener) mailserver_instance, new LeaseRenewalManager());
System.out.println(">> Mail Server bereit");
System
}
catch(Exception e)
catch
{
System.out.println("##### mm: exception caught: ");
System
e.printStackTrace();
}
}
}
f.) mm.services.msgboard
Dieses Package enthält Klassen des Messageboard-Dienstes.
Klasse
Message
MessageBoardServer
MessageBoardServerImpl
RegisterMessageBoardServer
Bedeutung
Stellt eine Nachricht dar
Das Remote-Interface des MessageboardDienstes
Die Implementation des MessageboardDienstes
Instantiiert einen Messageboard-Dienst und
registriert ihn beim Lookup Service
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.services.msgboard.Message
java.lang.Object
|
+----mm.services.msgboard.Message
public class Message
extends java.lang.Object
implements java.io.Serializable
Dies ist die Repräsentation eine Nachricht in dem Message Board.
Version:
1.0
Author:
Stefan Zier
Message(String, String, String, String, String, Date)
Erstellt eine Message.
addReply(Message)
Fügt eine Antwort hinzu
getBoard()
Liefert das Board der Nachricht zurück
getBody()
Liefert den Text der Nachricht zurück
getCreated()
Liefert das Datum an dem die Nachricht gepostet wurde zurück.
getId()
Liefert die ID der Nachricht zurück.
getReplies()
Liefert die Liste der Antworten auf diese Nachricht zurück.
getSender()
Liefert den Absender der Nachricht zurück.
getSubject()
Liefert das Subject der Nachricht zurück.
hasReplies()
Liefert true zurück wenn die Nachricht Antworten hat.
Message
public Message(java.lang.String id,
java.lang.String board,
java.lang.String sender,
java.lang.String subject,
java.lang.String body,
java.util.Date created)
Erstellt eine Message.
Parameters:
id - die ID der Message
board - das Board der Message
sender - der Versender der Nachricht
subject - das Subject der Nachricht
body - der Text der Nachricht
created - das Datum an dem die Nachricht erstellt wurde
getId
public java.lang.String getId()
Liefert die ID der Nachricht zurück.
Returns:
die ID der Nachricht
getBoard
public java.lang.String getBoard()
Liefert das Board der Nachricht zurück
Returns:
das Board der Nachricht.
getSender
public java.lang.String getSender()
Liefert den Absender der Nachricht zurück.
Returns:
den Absender der Nachricht.
getSubject
public java.lang.String getSubject()
Liefert das Subject der Nachricht zurück.
Returns:
das Subject der Nachricht
getBody
public java.lang.String getBody()
Liefert den Text der Nachricht zurück
Returns:
den Text der Nachricht.
getCreated
public java.util.Date getCreated()
Liefert das Datum an dem die Nachricht gepostet wurde zurück.
Returns:
das Datum an dem die Nachricht gepostet wurde
getReplies
public java.util.Vector getReplies()
Liefert die Liste der Antworten auf diese Nachricht zurück.
Returns:
einen Vector mit Message-Objekten
hasReplies
public boolean hasReplies()
Liefert true zurück wenn die Nachricht Antworten hat.
Returns:
true wenn die Nachricht antworten hat
addReply
public void addReply(Message reply)
Fügt eine Antwort hinzu
Parameters:
message - die Antwort
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.msgboard;
import java.util.Date;
import java.util.Vector;
import java.io.Serializable;
/**
* Dies ist die Repräsentation eine Nachricht in dem Message Board .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Message implements Serializable
{
private String id = null;
private String board = null;
private String sender = null;
private String subject = null;
private String body = null;
private Date created = null;
private Vector replies = null;
/**
* Erstellt eine Message.
*
* @param id die ID der Message
Messag
* @param board das Board der Messag e
* @param sender der Versender der Nachrich t
* @param subject das Subject der Nachrich t
* @param body der Text der Nachrich t
* @param created das Datum an dem die Nachricht erstellt wurd e
*/
public Message(String id, String board, String sender, String subject,
String body, Date created)
{
this.id = id;
this
this.board = board;
this
this.sender = sender;
this
this.subject = subject;
this
this.body = body;
this
this.created = created;
this
replies = new Vector();
}
/**
* Liefert die ID der Nachricht zurück .
*
* @return die ID der Nachricht
Nachrich
*/
public String getId()
{
return id;
}
/**
* Liefert das Board der Nachricht zurüc k
*
* @return das Board der Nachricht.
Nachricht
*/
public String getBoard()
{
return board;
}
/**
* Liefert den Absender der Nachricht zurück .
*
* @return den Absender der Nachricht.
Nachricht
*/
public String getSender()
{
return sender;
}
/**
* Liefert das Subject der Nachricht zurück .
*
* @return das Subject der Nachricht
Nachrich
*/
public String getSubject()
{
return subject;
}
/**
* Liefert den Text der Nachricht zurüc k
*
* @return den Text der Nachricht.
Nachricht
*/
public String getBody()
{
return body;
}
/**
* Liefert das Datum an dem die Nachricht gepostet wurde zurück .
*
* @return das Datum an dem die Nachricht gepostet wurd e
*/
public Date getCreated()
{
return created;
}
/**
* Liefert die Liste der Antworten auf diese Nachricht zurück .
*
* @return einen Vector mit Message-Objekten
Message-Objekte
*/
public Vector getReplies()
{
return replies;
}
/**
* Liefert true zurück wenn die Nachricht Antworten hat .
*
* @return true wenn die Nachricht antworten ha t
*/
public boolean hasReplies()
{
return (replies.size() > 0);
}
/**
* Fügt eine Antwort hinzu
hinz
*
* @param message die Antwort
Antwor
*/
public void addReply(Message reply)
{
replies.addElement(reply);
replies
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface
mm.services.msgboard.MessageBoardServer
public interface MessageBoardServer
extends java.rmi.Remote, AliveCheckable
Dies ist das Interface zum Messageboard-Server. Jedes Messageboard wird
durch einen eindeutigen String identifiziert.
Version:
1.0
Author:
Stefan Zier
createMessage(String, String, String, String, String)
Erstellt eine neue Nachricht in dem angegebenen Messageboard.
deleteMessage(String, String)
Löscht eine Message mit einer bestimmten ID in einem Messageboard.
deleteMessageBoard(String)
Löscht ein Messageboard samt allen Messages.
getMessages(String)
Listet alle Nachrichten in einem Board auf.
createMessage
public void createMessage(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
board,
sender,
reply,
subject,
body) throws java.rmi.RemoteException
Erstellt eine neue Nachricht in dem angegebenen Messageboard.
Parameters:
Board - das MessageBoard in das der spieler die Nachricht
schreibt. Existiert das MessageBoard noch nicht so wird es
erstellt.
sender - der Name des Spielers, der die Nachricht sendet
- id der Message auf die der Spieler antwortet oder null
wenn er einen neuen Thread beginnt.
subject - das Subject der Nachricht
body - der Inhalt der Nachricht
reply
getMessages
public java.util.Vector getMessages(java.lang.String board) throws java.rmi.RemoteExceptio
Listet alle Nachrichten in einem Board auf. Dabei werden nur die
Nachrichten übertragen, die nicht eine Antwort sind.
Parameters:
board - das Messageboard
Returns:
einen Vector mit Message Objekten
deleteMessage
public void deleteMessage(java.lang.String board,
java.lang.String id) throws java.rmi.RemoteException
Löscht eine Message mit einer bestimmten ID in einem
Messageboard.
Parameters:
board - das Messageboard
id - die ID der Message die gelöscht werden soll.
deleteMessageBoard
public void deleteMessageBoard(java.lang.String board) throws java.rmi.RemoteException
Löscht ein Messageboard samt allen Messages.
Parameters:
board - das Messageboard
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.msgboard;
// Java core imports
import java.rmi.*;
// Jini extension imports
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.lookup.entry.Name;
import net.jini.lookup.entry.ServiceInfo;
import net.jini.core.entry.Entry;
/**
* Diese Klasse instantiiert den File server und registriert ihn bei m
Lookup Service.
Service
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class RegisterMessageBoardServer
{
static JoinManager jm;
static MessageBoardServerImpl msgboard_instance;
/**
* Main methode.
*/
public static void main(String[] argsv)
{
System.out.println("RegisterMessageBoardServer (c) 1999 MM
System
Jahresprojekt");
try
{
// install security manager so that we'll be able to talk to
server
System.out.println(">> installiere RMI Security manager...");
System
System.setSecurityManager(new RMISecurityManager());
System
// create service
System.out.println(">> instantiiere MessageBoard Server ...");
System
msgboard_instance = new MessageBoardServerImpl();
// this name will be seen to users that browse services
Name nameEntry = new Name("MM MessageBoard Server");
// some addtl. serivice information such as manufacterer etc.
ServiceInfo serviceInfo = new ServiceInfo("MM MessageBoard
Server", "CE5 WS 1999/2000",
"CE5 WS 1999/2000", "1.0", "", "");
// gather all information that we're going to pass on to the
lookup service
Entry entries[] = new Entry[] {nameEntry, serviceInfo};
System.out.println(">> registriere den MessageBoard Server beim
System
Lookup Service...");
// create a new join manager and have it register the
jts_instance.
jm = new JoinManager(msgboard_instance, entries,
(ServiceIDListener) msgboard_instance, new LeaseRenewalManager());
System.out.println(">> MessageBoard Server bereit");
System
}
catch(Exception e)
catch
{
System.out.println("##### mm: exception caught: ");
System
e.printStackTrace();
}
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class
mm.services.msgboard.MessageBoardServerImpl
mm.services.msgboard.MessageBoardServerImpl
public class MessageBoardServerImpl
implements MessageBoardServer
Implementation des MessageBoard Servers.
Version:
1.0
Author:
Stefan Zier
MessageBoardServerImpl()
Konstruktor.
createMessage(String, String, String, String, String)
Erstellt eine neue Nachricht in dem angegebenen Messageboard.
deleteMessage(String, String)
Löscht eine Message mit einer bestimmten ID in einem Messageboard.
deleteMessageBoard(String)
Löscht ein Messageboard samt allen Messages.
getMessages(String)
Listet alle Nachrichten in einem Board auf.
isAlive()
Gibt true zurück wenn alles mit dem FileServer in Ordnung ist.
serviceIDNotify(ServiceID)
Diese Methode wird vom Join Manager aufgerufen um dem Service
seine Service ID mitzuteilen so bald der Service registriert ist.
MessageBoardServerImpl
public MessageBoardServerImpl() throws java.rmi.RemoteException, java.sql.SQLException, ja
Konstruktor. Liest die Konfigurationsdatei und baut eine Verbindung
zur Datenbank auf.
createMessage
public void createMessage(java.lang.String
java.lang.String
java.lang.String
java.lang.String
java.lang.String
board,
sender,
reply,
subject,
body) throws java.rmi.RemoteException
Erstellt eine neue Nachricht in dem angegebenen Messageboard.
Parameters:
Board - das MessageBoard in das der spieler die Nachricht
schreibt. Existiert das MessageBoard noch nicht so wird es
erstellt.
sender - der Name des Spielers, der die Nachricht sendet
reply - id der Message auf die der Spieler antwortet oder null
wenn er einen neuen Thread beginnt.
subject - das Subject der Nachricht
body - der Inhalt der Nachricht
getMessages
public java.util.Vector getMessages(java.lang.String board) throws java.rmi.RemoteExceptio
Listet alle Nachrichten in einem Board auf. Dabei werden nur die
Nachrichten übertragen, die nicht eine Antwort sind.
Parameters:
board - das Messageboard
Returns:
einen Vector mit Message Objekten
deleteMessage
public void deleteMessage(java.lang.String board,
java.lang.String id) throws java.rmi.RemoteException
Löscht eine Message mit einer bestimmten ID in einem
Messageboard.
Parameters:
board - das Messageboard
id - die ID der Message die gelöscht werden soll.
deleteMessageBoard
public void deleteMessageBoard(java.lang.String board) throws java.rmi.RemoteException
package mm.services.msgboard;
// Java core imports
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.io.IOException;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Date;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
// Jini extension imports
import com.sun.jini.lookup.ServiceIDListener;
import net.jini.core.lookup.ServiceID;
// Database connection imports
import com.bitmechanic.sql.ConnectionPoolManager;
import com.bitmechanic.sql.ConnectionPool;
// MM Project imports
import mm.tools.ConfigFile;
import mm.tools.Static;
/**
* Implementation des MessageBoard Servers.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class MessageBoardServerImpl extends UnicastRemoteObject implements
MessageBoardServer, ServiceIDListener
{
// database connections
private ConnectionPoolManager cpm = null;
private ConnectionPool pool = null;
;
/**
* Konstruktor. Liest die Konfigurationsdatei und baut eine Verbindun g
zur Datenbank auf.
auf
*/
public MessageBoardServerImpl()
throws RemoteException, SQLException, IOException,
ClassNotFoundException,
InstantiationException, IllegalAccessException
InstantiationException
{
super();
super
ConfigFile configfile = new
ConfigFile("f:\\mm\\services\\msgboard\\msgboardserver.properties");
// create a connection pool manager
cpm = new ConnectionPoolManager(120);
// get
String
String
String
url, username and password from the configuration file
url = configfile.get("msgboard.database.URL");
username = configfile.get("msgboard.database.username");
password = configfile.get("msgboard.database.password");
if
if(url
== null || url.equals(""))
{
throw new IllegalArgumentException("mm: no database URL given");
}
if(username == null || username.equals(""))
if
{
throw new IllegalArgumentException("mm: no database login given");
}
if(password == null || password.equals(""))
if
{
throw new IllegalArgumentException("mm: no database password
given");
}
// add the alias for "our" database
cpm.addAlias("msgboard", "org.gjt.mm.mysql.Driver", url, username,
cpm
password, 120, 300, 120);
pool = cpm.getPool("msgboard");
}
/**
* Erstellt eine neue Nachricht in dem angegebenen Messageboard.
*
* @param Board das MessageBoard in das der spieler die Nachrich t
schreibt.
schreibt
*
Existiert das MessageBoard noch nicht so wird es erstellt.
* @param sender der Name des Spielers, der die Nachricht sende t
* @param reply id der Message auf die der Spieler antwortet oder nul l
wenn
wen
*
er einen neuen Thread beginnt.
* @param subject das Subject der Nachrich t
* @param body der Inhalt der Nachrich t
*/
public void createMessage(String board, String sender, String reply,
String subject,
String body)
throws RemoteException
{
// Attribute überprüfen
if(Static.empty(board))
if
throw new IllegalArgumentException("mm: board may not be empty");
if(Static.empty(sender))
if
throw new IllegalArgumentException("mm: sender may not be empty");
try
{
// Datenbankverbindung aus dem Pool holen
Connection conn = pool.getConnection();
// maximale ID herausfinden
String query = "SELECT MAX(id) AS maxid FROM msgboard";
Statement sGetMaxId = conn.createStatement();
ResultSet rsGetMaxId = sGetMaxId.executeQuery(query);
int maxid = 1;
;
if(rsGetMaxId.next())
if
{
maxid = rsGetMaxId.getInt("maxid") + 1;
}
sGetMaxId.close();
sGetMaxId
// query zusammenbauen
query = "INSERT INTO msgboard (id, board, sender, subject, body,
reply, created) values(";
query += maxid;
query += ", ";
query += Static.sqlString(board);
query += ", ";
query += Static.sqlString(sender);
query += ", ";
query += Static.sqlString(subject);
query += ", ";
query += Static.sqlString(body);
query += ", ";
query += reply;
query += ", ";
query += Static.mysqlDate(new Date());
query += ")";
// query ausführen
Statement sInsertMessage = conn.createStatement();
sInsertMessage.execute(query);
sInsertMessage
sInsertMessage.close();
sInsertMessage
// Datenbankverbindung in den Pool zurückgeben
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: error using database", sql);
}
}
/**
* Listet alle Nachrichten in einem Board auf. Dabei werden nur di e
Nachrichte
Nachrichten
* übertragen, die nicht eine Antwort sind.
*
* @param board das Messageboard
Messageboar
* @return einen Vector mit Message Objekte n
*/
public Vector getMessages(String board)
throws RemoteException
{
try
{
// conn holen
Connection conn = pool.getConnection();
// erst mal alle Nachrichten aus der Datenbank reinziehen
Hashtable messages = new Hashtable();
Vector tmp = new Vector();
// query bauen
String query = "SELECT id, body, subject, sender, created FROM
msgboard WHERE board=" + Static.sqlString(board) + " ORDER BY created
DESC";
// query machen
Statement sGetMessages = conn.createStatement();
ResultSet rsGetMessages = sGetMessages.executeQuery(query);
// messages in den Vector schreiben
while(rsGetMessages.next())
while
{
// record auslesen
String id = rsGetMessages.getString("id");
String body = rsGetMessages.getString("body");
String subject = rsGetMessages.getString("subject");
String sender = rsGetMessages.getString("sender");
Date created = rsGetMessages.getDate("created");
// message objekt erzeugen
Message message = new Message(id, board, sender, subject, body,
created);
// message objekt in die hashtable schreiben
messages.put(id, message);
messages
// message objekt in den vektor schreiben
tmp.addElement(message);
tmp
}
sGetMessages.close();
sGetMessages
// so, nun bauen wir die baumstruktur. dazu lesen wir alle
nachrichten aus, die was im reply
// feld stehen haben. wir verlinken die nachricht jeweils mit der
übernachricht und löschen
// sie aus dem vektor, wir verschieben sie also von der obersten
ebene des baums an den platz
// an den sie gehört.
// query II bauen
query = "SELECT id, reply FROM msgboard WHERE board=" +
Static.sqlString(board) + " AND reply NOT NULL ORDER BY created DESC" ;
// query machen
Statement sGetReplies = conn.createStatement();
ResultSet rsGetReplies = sGetReplies.executeQuery(query);
while
while(rsGetReplies.next())
{
// record lesen
String id = rsGetReplies.getString("id");
String reply = rsGetReplies.getString("reply");
// message suchen
Message to_move = (Message) messages.get(id);
// message aus Vector löschen
tmp.removeElement(to_move);
tmp
// übermessage suchen
Message top_msg = (Message) messages.get(reply);
// message anhängen
top_msg.addReply(to_move);
top_msg
}
sGetReplies.close();
sGetReplies
// conn zurück
conn.close();
conn
// Vector zurückgeben
return tmp;
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: could not get the messages from the
database due to a database error", sql);
}
}
/**
* Löscht eine Message mit einer bestimmten ID in einem Messageboard .
*
* @param board das Messageboard
Messageboar
* @param id die ID der Message die gelöscht werden soll .
*/
public void deleteMessage(String board, String id)
throws RemoteException
{
try
{
// Connection aus dem Pool holen
Connection conn = pool.getConnection();
// query basteln
String query = "DELETE FROM msgboard WHERE board=" +
Static.sqlString(board) +
" AND id=" + id;
// query ausführen
Statement sDeleteMessage = conn.createStatement();
sDeleteMessage.execute(query);
sDeleteMessage
sDeleteMessage.close();
sDeleteMessage
// Connection zurück in den Pool
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: could not execute delete in
database", sql);
}
}
/**
* Löscht ein Messageboard samt allen Messages .
*
* @param board das Messageboard
Messageboar
*/
public void deleteMessageBoard(String board)
throws RemoteException
{
try
{
// Connection aus dem Pool holen
Connection conn = pool.getConnection();
// query basteln
String query = "DELETE FROM msgboard WHERE board=" +
Static.sqlString(board);
// query ausführen
Statement sDeleteMessage = conn.createStatement();
sDeleteMessage.execute(query);
sDeleteMessage
sDeleteMessage.close();
sDeleteMessage
// Connection zurück in den Pool
conn.close();
conn
}
catch(SQLException sql)
catch
{
throw new RemoteException("mm: could not execute delete in
database", sql);
}
}
/**
* Diese Methode wird vom Join Manager aufgerufen um dem Service sein e
Service ID mitzuteilen
mitzuteile
* so bald der Service registriert ist .
*
* @param service_id Service ID
I
*/
public void serviceIDNotify(ServiceID service_id)
{
System.out.print("Service registered, ID: ");
System
System.out.println(service_id);
System
}
/**
* Gibt true zurück wenn alles mit dem FileServer in Ordnung ist .
*
* @return true wenn alles mit dem FileServer in Ordnung ist .
*/
public boolean isAlive()
throws RemoteException
{
// check the database connection
try
{
// kleine Testquery
Connection conn = pool.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT checkvalue FROM
checktable");
if(rs.next())
if
{
String weltherrschaft = rs.getString("checkvalue");
if(weltherrschaft == null ||
if
!weltherrschaft.equalsIgnoreCase("WELTHERRSCHAFT"))
return false;
}
else
return false;
s.close();
conn.close();
conn
}
catch(SQLException sql)
catch
{
return false;
}
return true;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class
mm.services.msgboard.RegisterMessageBoardServer
java.lang.Object
|
+----mm.services.msgboard.RegisterMessageBoardServer
public class RegisterMessageBoardServer
extends java.lang.Object
Diese Klasse instantiiert den File server und registriert ihn beim Lookup
Service.
Version:
1.0
Author:
Stefan Zier
RegisterMessageBoardServer()
main(String[])
Main methode.
RegisterMessageBoardServer
public RegisterMessageBoardServer()
main
public static void main(java.lang.String argsv[])
Main methode.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.services.msgboard;
// Java core imports
import java.rmi.*;
// Jini extension imports
import com.sun.jini.lookup.JoinManager;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.lookup.entry.Name;
import net.jini.lookup.entry.ServiceInfo;
import net.jini.core.entry.Entry;
/**
* Diese Klasse instantiiert den File server und registriert ihn bei m
Lookup Service.
Service
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class RegisterMessageBoardServer
{
static JoinManager jm;
static MessageBoardServerImpl msgboard_instance;
/**
* Main methode.
*/
public static void main(String[] argsv)
{
System.out.println("RegisterMessageBoardServer (c) 1999 MM
System
Jahresprojekt");
try
{
// install security manager so that we'll be able to talk to
server
System.out.println(">> installiere RMI Security manager...");
System
System.setSecurityManager(new RMISecurityManager());
System
// create service
System.out.println(">> instantiiere MessageBoard Server ...");
System
msgboard_instance = new MessageBoardServerImpl();
// this name will be seen to users that browse services
Name nameEntry = new Name("MM MessageBoard Server");
// some addtl. serivice information such as manufacterer etc.
ServiceInfo serviceInfo = new ServiceInfo("MM MessageBoard
Server", "CE5 WS 1999/2000",
"CE5 WS 1999/2000", "1.0", "", "");
// gather all information that we're going to pass on to the
lookup service
Entry entries[] = new Entry[] {nameEntry, serviceInfo};
System.out.println(">> registriere den MessageBoard Server beim
System
Lookup Service...");
// create a new join manager and have it register the
jts_instance.
jm = new JoinManager(msgboard_instance, entries,
(ServiceIDListener) msgboard_instance, new LeaseRenewalManager());
System.out.println(">> MessageBoard Server bereit");
System
}
catch(Exception e)
catch
{
System.out.println("##### mm: exception caught: ");
System
e.printStackTrace();
}
}
}
g.) mm.tools
Dieses Package enthält einige Hilfsklassen.
Klasse
AliveCheckable
Backup
BreakPoint
ConfigFile
Static
TextFiles
Bedeutung
Interface für Klassen, um zu prüfen ob
Dienste noch laufen.
Minimales Backup-Programm
Debugging-Hilfe
Klasse zum laden und parsen eines
Konfigurationsfiles
Sammlung hilfreicher statischer Methoden
Vereinfachtes Handling von Textdateien
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface mm.tools.AliveCheckable
public interface AliveCheckable
extends java.rmi.Remote
Wird von Jini Services implementiert und kann von Clients verwendet
werden um festzustellen, ob der Server noch voll funktionstüchtig ist.
Version:
1.0
Author:
Stefan Zier
isAlive()
Gibt true zurück, wenn der geprüfte Service 100%ig einsatzfähig ist,
d.h.
isAlive
public boolean isAlive() throws java.rmi.RemoteException
Gibt true zurück, wenn der geprüfte Service 100%ig einsatzfähig ist,
d.h. beispielsweise alle Datenbankverbindungen funktionieren etc.
Returns:
true, wenn alles in Ordnung ist
Throws:
java.rmi.RemoteException - wenn schon die Kommunikation mit
dem Service nicht funktioniert.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* Wird von Jini Services implementiert und kann von Clients verwende t
werden um festzustellen,
* ob der Server noch voll funktionstüchtig ist.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public interface AliveCheckable extends Remote
{
/**
* Gibt true zurück, wenn der geprüfte Service 100%ig einsatzfähig ist ,
d.h. beispielsweise
beispielsweis
* alle Datenbankverbindungen funktionieren etc.
etc
*
* @return true, wenn alles in Ordnung is t
* @exception RemoteException wenn schon die Kommunikation mit de m
Service nicht funktioniert.
funktioniert
*/
public boolean isAlive()
throws RemoteException;
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.tools.Backup
java.lang.Object
|
+----mm.tools.Backup
public class Backup
extends java.lang.Object
Diese kleine Toolklasse erstellt ein Backup von allen Dateien des Pojektes.
Dafür erstellt sie
Version:
1.0
Author:
Stefan Zier
destination
out
prefix
source
Backup()
backup(File)
fit(String, int, char, boolean)
this adds characters to a string until it reaches a certain length
fitNumber(int, int)
this fits a number to a certain length
fitNumber(String, int)
this fits a number to a certain length
main(String[])
source
public static java.lang.String source
destination
public static java.lang.String destination
prefix
public static java.lang.String prefix
out
public static java.util.zip.ZipOutputStream out
Backup
public Backup()
backup
public static void backup(java.io.File file) throws java.io.IOException
main
public static void main(java.lang.String args[])
fit
public static java.lang.String fit(java.lang.String what,
int howlong,
char filler,
boolean left)
this adds characters to a string until it reaches a certain length
Parameters:
what - the source string
howlong - the final length of the string
filler - the char to fill the strinp up with
left - true if the character should be added
otherwiese false
Returns:
the result string
before the string,
fitNumber
public static java.lang.String fitNumber(java.lang.String number,
int howlong)
this fits a number to a certain length
Parameters:
number - the number
howlong - the final length
Returns:
the sized number string
fitNumber
public static java.lang.String fitNumber(int number,
int howlong)
this fits a number to a certain length
Parameters:
number - the number
howlong - the final length
Returns:
the sized number string
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
import
import
import
import
import
import
import
import
java.util.zip.ZipOutputStream;
java.util.zip.ZipEntry;
java.util.Date;
java.util.GregorianCalendar;
java.io.FileOutputStream;
java.io.FileInputStream;
java.io.File;
java.io.IOException;
/**
* Diese kleine Toolklasse erstellt ein Backup von allen Dateien de s
Pojektes. Dafür erstellt
* sie
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Backup
{
public static String source="F:\\mm";
public static String destination="D:\\Backups";
public static String prefix="MM Backup ";
public static ZipOutputStream out = null;
public static void backup(File file)
throws IOException
{
if(file.isDirectory())
if
{
System.out.println(">> d: " + file.getPath());
System
String[] subfiles = file.list();
String
for
for(int
i=subfiles.length-1; i>=0; i--)
backup(new File(file.getPath() + "/" + subfiles[i]));
backup
}
else
{
System.out.println(">> f: " + file.getPath());
System
// calculate the relative path
String rel_path = Static.replace(file.getPath(), source, "");
// create a new ZIP-Entry
ZipEntry ze = new ZipEntry(rel_path);
// put the new ZIP-Entry
out.putNextEntry(ze);
out
// open the source file
FileInputStream in = new FileInputStream(file);
// the buffer
byte[] buf = new byte[10000];
byte
while
while(in.available()
> 0)
{
int result = in.read(buf);
out.write(buf, 0, result-1);
out
}
in.close();
in
}
}
public static void main(String[] args)
{
System.out.println("Backup started");
System
// get the current date
Date date = new Date();
// set calendar to date
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
cal
StringBuffer date_str = new StringBuffer();
date_str
date_str.append(destination);
date_str.append("/");
date_str
date_str.append(prefix);
date_str
int tmp = cal.get(cal.YEAR);
date_str
date_str.append(String.valueOf(tmp));
tmp = cal.get(cal.MONTH);
date_str.append(fitNumber(tmp, 2));
date_str
tmp = cal.get(cal.DATE);
date_str.append(fitNumber(tmp, 2));
date_str
tmp = cal.get(cal.HOUR);
date_str.append(fitNumber(tmp, 2));
date_str
tmp = cal.get(cal.MINUTE);
date_str.append(fitNumber(tmp, 2));
date_str
tmp = cal.get(cal.SECOND);
date_str.append(fitNumber(tmp, 2));
date_str
date_str.append(".zip");
date_str
System.out.println(">> backing up to \"" + date_str.toString() +
System
"\"");
try
{
// create the file
FileOutputStream fos = new FileOutputStream(date_str.toString());
out = new ZipOutputStream(fos);
backup(new File(source));
backup
out
out.close();
fos.close();
fos
}
catch(Exception e)
catch
{
e.printStackTrace();
}
}
/**
* this adds characters to a string until it reaches a certain lengt h
*
* @param what the source string
strin
* @param howlong the final length of the strin g
* @param filler the char to fill the strinp up wit h
* @param left true if the character should be added before the string ,
otherwiese false
fals
* @return the result string
*/
public static String fit(String what, int howlong, char filler, boolean
left)
{
String tmp = what;
if(tmp == null)
if
tmp = new String();
while
while(tmp.length()
< howlong)
{
if(left)
if
tmp = String.valueOf(filler) + tmp;
else
tmp = tmp + String.valueOf(filler);
}
return tmp;
}
/**
* this fits a number to a certain lengt h
*
* @param number the number
numbe
* @param howlong the final length
lengt
* @return the sized number string
strin
*/
public static String fitNumber(String number, int howlong)
{
return fit(number, howlong, "0".charAt(0), true);
}
/**
* this fits a number to a certain lengt h
*
* @param number the number
numbe
* @param howlong the final length
lengt
* @return the sized number string
strin
*/
public static String fitNumber(int number, int howlong)
{
return fit(String.valueOf(number), howlong, "0".charAt(0), true);
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.tools.BreakPoint
java.lang.Object
|
+----mm.tools.BreakPoint
public class BreakPoint
extends java.lang.Object
this is a little but nice tool for server side java development. Every call to
the now() method outputs a string on the screen.
Version:
1.0 - 08/12/1999
Author:
Stefan Zier
BreakPoint()
now(Object, String)
this method is called whenever a breakpoint is reached
now(String)
reset()
reset the counter to zero
BreakPoint
public BreakPoint()
now
public static void now(java.lang.Object where,
java.lang.String info)
this method is called whenever a breakpoint is reached
Parameters:
where - the object in which the breakpoint occurred
info - additional information
now
public static void now(java.lang.String info)
reset
public static void reset()
reset the counter to zero
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
/**
* this is a little but nice tool for server side java development. Ever y
call to
* the now() method outputs a string on the screen .
*
* @author Stefan Zier
Zie
* @version 1.0 - 08/12/1999
08/12/199
*/
public class BreakPoint
{
private static int counter = 0;
/**
* this method is called whenever a breakpoint is reache d
*
* @param where the object in which the breakpoint occurre d
* @param info additional information
informatio
*/
public static void now(Object where, String info)
{
counter++;
counter
System.out.print("****[" + counter + "]**");
System
if(where != null)
if
{
System.out.print("[" + where.getClass().getName() + "]");
System
}
if(info != null)
if
{
System.out.print(info);
System
}
System.out.println();
System
}
public static void now(String info)
{
now(null, info);
now
}
/**
* reset the counter to zero
zer
*/
public static void reset()
{
counter = 0;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.tools.ConfigFile
java.lang.Object
|
+----mm.tools.ConfigFile
public class ConfigFile
extends java.lang.Object
This class loads a read-only config-file from the disk
Version:
1.0 - 07/08/1999
Author:
Stefan Zier
ConfigFile(String)
Initializes the table
get(String)
Looks a variable up in the table
keys()
this returns a list of all keys
ConfigFile
public ConfigFile(java.lang.String filename) throws java.lang.IllegalArgumentException, ja
Initializes the table
get
public java.lang.String get(java.lang.String varname)
Looks a variable up in the table
keys
public java.util.Enumeration keys()
this returns a list of all keys
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
import
import
import
import
import
java.util.Properties;
java.util.Enumeration;
java.io.FileNotFoundException;
java.io.IOException;
java.io.FileInputStream;
/**
* This class loads a read-only config-file from the dis k
*
* @author Stefan Zier
Zie
* @version 1.0 - 07/08/1999
07/08/199
*/
public class ConfigFile
{
protected Properties config;
/**
* Initializes the table
tabl
*/
public ConfigFile(String filename)
throws IllegalArgumentException, FileNotFoundException, IOException
{
// check if the filename is null
if(filename == null)
if
throw new IllegalArgumentException("o Trying to load null config
file !");
// open the file
FileInputStream fis = new FileInputStream(filename);
// load the file
config = new Properties();
config.load(fis);
config
fis.close();
fis
}
/**
* Looks a variable up in the tabl e
*/
public String get(String varname)
{
return config.getProperty(varname);
}
/**
* this returns a list of all key s
*/
public Enumeration keys()
{
return config.keys();
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.tools.Static
java.lang.Object
|
+----mm.tools.Static
public class Static
extends java.lang.Object
this class offers some static methods (e.g. date conversion)
Version:
1.0 - created 07/08/1999
Author:
Stefan Zier
EMAIL_CONTAINS_WS
EMAIL_EMPTY
EMAIL_INVALID_CHARS
EMAIL_INVALID_FORMAT
EMAIL_INVALID_TLD
EMAIL_OK
MAX_EXCEEDED
MIN_EXCEEDED
random
SIZE_OK
Static()
beginsUppercase(String)
this simple function finds out whether the word starts with an
uppercase Character or not can handle Umlauts like Ö
booleanToString(boolean)
this little method converts boolean values to strings.
checkSize(String, int, int)
This will check if the size of a String is correct.
containsWhitespaces(String)
this checks whether a string contains any whitespaces
cutString(String, int)
This cuts Strings after a certain length and attaches "..."
dayString(int)
Returns a String containing the name of the day.
emailCheck(String)
Checks whether an email address is syntactically correct or not and
returns the result as an int constant.
emailValid(String)
Checks whether an email address is syntactically correct.
emailVerbose(String)
Checks whether an email address is syntactically correct or not and
returns the result in verbal form.
empty(String)
this one checks wether a string is null, empty or contains only
whitespaces
fit(String, int, char, boolean)
this adds characters to a string until it reaches a certain length
fitNumber(int, int)
this fits a number to a certain length
fitNumber(String, int)
this fits a number to a certain length
formatDate(long)
This method will convert a date that is stored in a long into a US
formatted date in the form MM/DD/YYYY HH:MM.
formatFileSize(long)
This method will format a long value that symbolizes the size of a file
in bytes.
getQueryParam(String, Hashtable)
This will extract a usable String from a querystring hashtable that is
never null.
howManyDays(int, int)
this returns how many days a month has
httpGetString(String)
this converts a string into one that is compatible for being used in a
link with get-parameters
insert (String, String, int)
this method is used to insert a string into another
javascriptString(String)
This method will treat a String so that it can be output to javascript
without problems.
mysqlDate(Date)
this converts a date into a MySQL-compliant string including the ' 's
nonNull(String)
this is used to make sure a string is not null (returns a "" string
instead)
oracleDate(Date)
this converts a date into a Oracle-compliant string including the ' 's
randomNumber(int)
This method will return a String containing a random number in the
length given.
recursiveDelete(File)
This method will remove this folder and all its subfolders.
remove(String, String)
this is used to do find and remove operations within strings
removeSurroundingWhitespaces(String)
this is used to remove whitespaces before and after a string only.
removeWhitespaces(String)
this is used to remove whitespaces such as spaces, tabs and cariage
returns from strings.
replace(String, String, String)
this is used to do find and replace operations within strings
sortStrings(String[])
This method sorts an array of Strings.
sortStrings(String[], int, int)
This method sorts an array of Strings.
sqlLikeString(String)
this is used to make sure a string is SQL compliant for like
sqlString(String)
this is used to make sure a string is SQL compliant
stringToBoolean(String)
this converts a string containing either "0" or "1" into the
corresponding boolean value.
whitespaceList(String)
this creates a Properties object from a whitespace/comma/semicolon
separated word list in a string.
SIZE_OK
public static final int SIZE_OK
MAX_EXCEEDED
public static final int MAX_EXCEEDED
MIN_EXCEEDED
public static final int MIN_EXCEEDED
random
public static java.util.Random random
EMAIL_OK
public static final int EMAIL_OK
EMAIL_EMPTY
public static final int EMAIL_EMPTY
EMAIL_CONTAINS_WS
public static final int EMAIL_CONTAINS_WS
EMAIL_INVALID_FORMAT
public static final int EMAIL_INVALID_FORMAT
EMAIL_INVALID_CHARS
public static final int EMAIL_INVALID_CHARS
EMAIL_INVALID_TLD
public static final int EMAIL_INVALID_TLD
Static
public Static()
insert
public static java.lang.String insert(java.lang.String in,
java.lang.String fill_in,
int pos)
this method is used to insert a string into another
Parameters:
in - the string that the other string is to be inserted in
fill_in - the string that is going to be inserted
pos - the position in which to fill in the string
Returns:
the resulting string
replace
public static java.lang.String replace(java.lang.String inp,
java.lang.String find,
java.lang.String what)
this is used to do find and replace operations within strings
Parameters:
in - the source string
find - what to find in the source string
what - what to write instead of
Returns:
replaced string
remove
public static java.lang.String remove(java.lang.String inp,
java.lang.String find)
this is used to do find and remove operations within strings
Parameters:
in - the source string
find - what to find in the source string
Returns:
replaced string
removeWhitespaces
public static java.lang.String removeWhitespaces(java.lang.String in)
this is used to remove whitespaces such as spaces, tabs and
cariage returns from strings.
Parameters:
in - the source string
Returns:
the string without whitespaces
removeSurroundingWhitespaces
public static java.lang.String removeSurroundingWhitespaces(java.lang.String in)
this is used to remove whitespaces before and after a string only. It
leaves whitespaces within the string untouched
Parameters:
in - the string to be processed
Returns:
the string without whitespaces before and after it
containsWhitespaces
public static boolean containsWhitespaces(java.lang.String in)
this checks whether a string contains any whitespaces
Parameters:
in - the string to check for whitespaces
Returns:
true, if it contains whitespaces
beginsUppercase
public static boolean beginsUppercase(java.lang.String word)
this simple function finds out whether the word starts with an
uppercase Character or not can handle Umlauts like Ö
Parameters:
word - the word
Returns:
true if the first character is uppercase
nonNull
public static java.lang.String nonNull(java.lang.String in)
this is used to make sure a string is not null (returns a "" string
instead)
Parameters:
in - the source string
Returns:
the non-null string
empty
public static boolean empty(java.lang.String in)
this one checks wether a string is null, empty or contains only
whitespaces
Parameters:
in - the string to check
Returns:
false if the string contains characters
fit
public static java.lang.String fit(java.lang.String what,
int howlong,
char filler,
boolean left)
this adds characters to a string until it reaches a certain length
Parameters:
what - the source string
howlong - the final length of the string
filler - the char to fill the strinp up with
left - true if the character should be added before the string,
otherwiese false
Returns:
the result string
fitNumber
public static java.lang.String fitNumber(java.lang.String number,
int howlong)
this fits a number to a certain length
Parameters:
number - the number
howlong - the final length
Returns:
the sized number string
fitNumber
public static java.lang.String fitNumber(int number,
int howlong)
this fits a number to a certain length
Parameters:
number - the number
howlong - the final length
Returns:
the sized number string
formatFileSize
public static java.lang.String formatFileSize(long length)
This method will format a long value that symbolizes the size of a
file in bytes.
Parameters:
length - the length of the file
Returns:
the formatted length
httpGetString
public static java.lang.String httpGetString(java.lang.String input)
this converts a string into one that is compatible for being used in a
link with get-parameters
Parameters:
input - the inputstring
Returns:
the correct string
oracleDate
public static java.lang.String oracleDate(java.util.Date date)
this converts a date into a Oracle-compliant string including the ' 's
Parameters:
date - a date
Returns:
the string
mysqlDate
public static java.lang.String mysqlDate(java.util.Date date)
this converts a date into a MySQL-compliant string including the ' 's
Parameters:
date - a date
Returns:
the string
sqlString
public static java.lang.String sqlString(java.lang.String in)
this is used to make sure a string is SQL compliant
Parameters:
in - the source string
Returns:
SQL compliant string
sqlLikeString
public static java.lang.String sqlLikeString(java.lang.String in)
this is used to make sure a string is SQL compliant for like
Parameters:
in - the source string
Returns:
SQL compliant string
booleanToString
public static java.lang.String booleanToString(boolean in)
this little method converts boolean values to strings. Unlike the
String.toString(boolean) function it doesn't convert to "true" or "false" but
to:
true -> "1"
false --> "0"
Parameters:
in - the boolean value
Returns:
the String
stringToBoolean
public static boolean stringToBoolean(java.lang.String in)
this converts a string containing either "0" or "1" into the
corresponding boolean value. All other values of the string return false.
Parameters:
in - the String
Returns:
the boolean equivalent of the String
whitespaceList
public static java.util.Properties whitespaceList(java.lang.String wordlist)
this creates a Properties object from a whitespace/comma/semicolon
separated word list in a string. The values of the words are set to null
Parameters:
wordlist - the word list
Returns:
the Properties object
getQueryParam
public static java.lang.String getQueryParam(java.lang.String param_name,
java.util.Hashtable querystring)
This will extract a usable String from a querystring hashtable that is
never null.
Parameters:
param_name - the name of the parameter to get
q Returns:
a String
checkSize
public static int checkSize(java.lang.String input,
int min,
int max)
This will check if the size of a String is correct.
Parameters:
input - the input String
min - the minimum length
max - the maximum length
Returns:
SIZE_OK, if the size is ok, MAX_EXCEEDED or MIN_EXCEEDED if
not.
randomNumber
public static java.lang.String randomNumber(int length)
This method will return a String containing a random number in the
length given.
Parameters:
length Returns:
a random number in the requested length
howManyDays
public static int howManyDays(int month,
int year)
this returns how many days a month has
Parameters:
month - the month to look for
year - the year to look for
Returns:
the number of days
dayString
public static java.lang.String dayString(int day)
Returns a String containing the name of the day.
Returns:
a String containing the name of the day.
formatDate
public static java.lang.String formatDate(long theTime)
This method will convert a date that is stored in a long into a US
formatted date in the form MM/DD/YYYY HH:MM.
Parameters:
theTime - long the date
Returns:
the String containing the formatted date, null if the date is
undefined
sortStrings
public static void sortStrings(java.lang.String strings[])
This method sorts an array of Strings. The algorithm used is a
mergesort, a modified version of quicksort that works better on arrays with
fixed size.
Parameters:
strings - the array to sort
sortStrings
public static void sortStrings(java.lang.String strings[],
int lo,
int hi)
This method sorts an array of Strings. The algorithm used is a
mergesort, a modified version of quicksort that works better on arrays with
fixed size.
Parameters:
strings - the array to sort
start - the index to start at
end - the index to end at
javascriptString
public static java.lang.String javascriptString(java.lang.String input)
This method will treat a String so that it can be output to javascript
without problems.
Parameters:
input - the input String
Returns:
the java script compliant String
cutString
public static java.lang.String cutString(java.lang.String input,
int length)
This cuts Strings after a certain length and attaches "..."
Parameters:
input - the source String
length - the length the output String is suppoed to have
Returns:
the cut String
emailVerbose
public static java.lang.String emailVerbose(java.lang.String email)
Checks whether an email address is syntactically correct or not and
returns the result in verbal form.
Parameters:
email - The address to check.
Returns:
The verbose result of the check.
emailValid
public static boolean emailValid(java.lang.String email)
Checks whether an email address is syntactically correct.
Parameters:
email - The address to check.
Returns:
True if the email is valid.
emailCheck
public static int emailCheck(java.lang.String email)
Checks whether an email address is syntactically correct or not and
returns the result as an int constant.
Parameters:
email - The address to check.
Returns:
The int result of the check.
recursiveDelete
public static boolean recursiveDelete(java.io.File rotten)
This method will remove this folder and all its subfolders.
Returns:
true if the action completed successfully
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
import
import
import
import
import
import
import
import
java.util.Properties;
java.util.StringTokenizer;
java.util.Random;
java.io.File;
java.util.Date;
java.util.Calendar;
java.util.GregorianCalendar;
java.util.Hashtable;
/**
* this class offers some static method s
* (e.g. date conversion)
conversion
*
* @author Stefan Zier
Zie
* @version 1.0 - created 07/08/1999
07/08/199
*/
public class Static
{
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// M E T H O D S
T H A T
java.lang.String
S H O U L D
H A V
E
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------/**
* this method is used to insert a string into anothe r
*
* @param in the string that the other string is to be inserted i n
* @param fill_in the string that is going to be inserte d
* @param pos the position in which to fill in the strin g
* @return the resulting string
strin
*/
public synchronized static String insert(String in, String fill_in, int
pos)
{
// is the string ok ?
if(in == null)
if
return null;
// is the pos ok ?
if(pos < 0 || pos > in.length() - 1)
if
return in;
// do we need to do anything ?
if(fill_in == null)
if
return in;
if(fill_in.equals(""))
if
return in;
if(in.equals(""))
if
return fill_in;
StringBuffer tmp = new StringBuffer(512);
tmp
tmp.append(in.substring(0,
pos));
tmp.append(fill_in);
tmp
tmp.append(in.substring(pos));
tmp
return tmp.toString();
}
/**
* this is used to do find and replace operations within string s
*
* @param in the source string
* @param find what to find in the source strin g
* @param what what to write instead o f
* @return replaced string
strin
*/
public static String replace(String inp, String find, String what)
{
// check if we need to search
if(inp == null || find == null || what == null)
if
return inp;
if(inp.equals("") || find.equals(""))
if
return inp;
// do the replacements
StringBuffer tmp = new StringBuffer(1024);
String in = new String(inp);
int length = find.length();
while
while(in.indexOf(find)
!= -1)
{
// copy everythng before the first match to tmp
tmp.append(in.substring(0, in.indexOf(find)));
tmp
)));
// append what to tmp
tmp.append(what);
tmp
// cut until the end of the first match from tmp
in = in.substring(in.indexOf(find) + length);
}
tmp.append(in);
tmp
return tmp.toString();
}
/**
* this is used to do find and remove operations within string s
*
* @param in the source string
* @param find what to find in the source strin g
* @return replaced string
strin
*/
public static String remove(String inp, String find)
{
// check if we need to search
if(inp == null || find == null)
if
return inp;
if(inp.equals("") || find.equals(""))
if
return inp;
// do the replacements
StringBuffer tmp = new StringBuffer(1024);
String in = new String(inp);
while
while(in.indexOf(find)
!= -1)
{
// copy evrthng before the first match to tmp
tmp.append(in.substring(0, in.indexOf(find)));
tmp
)));
// cut until the end of the first match from tmp
in = in.substring(in.indexOf(find) + find.length());
}
tmp.append(in);
tmp
return tmp.toString();
}
/**
* this is used to remove whitespaces such as spaces, tabs and cariag e
* returns from strings.
*
* @param in the source string
strin
* @return the string without whitespaces
whitespace
*/
public static String removeWhitespaces(String in)
{
// create a copy of the string
String tmp = new String(in);
// space
tmp = replace(tmp, " ", "");
// newline
tmp = replace(tmp,
// formfeed
tmp = replace(tmp,
// cariage return
tmp = replace(tmp,
// tab
tmp = replace(tmp,
// backspace
tmp = replace(tmp,
return tmp;
"\n", "");
"\f", "");
"\r", "");
"\t", "");
"\b", "");
}
/**
* this is used to remove whitespaces before and after a string only. I t
leaves
leave
* whitespaces within the string untouched
untouche
*
* @param in the string to be processe d
* @return the string without whitespaces before and after i t
*/
public static String removeSurroundingWhitespaces(String in)
{
// check if we got a faules Ei
if(in == null)
if
return null;
// maybe we should try the built-in String function
return in.trim();
}
/**
* this checks whether a string contains any whitespace s
*
* @param in the string to check for whitespace s
* @return true, if it contains whitespace s
*/
public static boolean containsWhitespaces(String in)
{
return (in.indexOf(" ") != -1 ||in.indexOf("\n") != -1 ||
in.indexOf("\f") != -1
|| in.indexOf("\r")
in
!= -1 || in.indexOf("\t") != -1 ||
in.indexOf("\b") != -1);
}
/**
* this simple function finds out whether the word starts with a n
uppercase Character or not
no
* can handle Umlauts like Ö
*
* @param word the word
wor
* @return true if the first character is uppercas e
*/
public static boolean beginsUppercase(String word)
{
if(word.substring(0,1).equals("&"))
if
{
// ok, so this is a Ö thing, let`s take care of the
second char
return
word.substring(1,1).equals(word.substring(1,1).toUpperCase());
}
// this is the normal case, let's stick with the first character.
return word.substring(0,1).equals(word.substring(0,1).toUpperCase());
}
/**
* this is used to make sure a string is not null (returns a "" strin g
instead)
instead
*
* @param in the source string
strin
* @return the non-null string
strin
*/
public static String nonNull(String in)
{
if(in == null)
if
return "";
else
return in;
}
/**
* this one checks wether a string is null, empty or contains onl y
whitespaces
whitespace
*
* @param in the string to check
chec
* @return false if the string contains character s
*/
public static boolean empty(String in)
{
if(in == null)
if
return true;
if(removeWhitespaces(in).equals(""))
if
return true;
return false;
}
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// F O R M A T T I N G
M E T H O D S
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------/**
* this adds characters to a string until it reaches a certain lengt h
*
* @param what the source string
strin
* @param howlong the final length of the strin g
* @param filler the char to fill the strinp up wit h
* @param left true if the character should be added before the string ,
otherwiese false
fals
* @return the result string
*/
public static String fit(String what, int howlong, char filler, boolean
left)
{
String tmp = nonNull(what);
while
while(tmp.length()
< howlong)
{
if(left)
if
tmp = String.valueOf(filler) + tmp;
else
tmp = tmp + String.valueOf(filler);
}
return tmp;
}
/**
* this fits a number to a certain lengt h
*
* @param number the number
numbe
* @param howlong the final length
lengt
* @return the sized number string
strin
*/
public static String fitNumber(String number, int howlong)
{
return fit(number, howlong, "0".charAt(0), true);
}
/**
* this fits a number to a certain lengt h
*
* @param number the number
numbe
* @param howlong the final length
lengt
* @return the sized number string
strin
*/
public static String fitNumber(int number, int howlong)
{
return fit(String.valueOf(number), howlong, "0".charAt(0), true);
}
// -- the chars (byte, kilobyte, Megabyte, Gigabyte, Terrabyte)
protected static String[] measure_chars = {" b", " k", " M", " G", "
T"};
/**
* This method will format a long value that symbolizes the size of
file in
i
* bytes.
*
* @param length the length of the fil e
* @return the formatted length
lengt
*/
public static String formatFileSize(long length)
{
double display = length;
a
StringBuffer result = new StringBuffer();
int measure = 0;
// make sure we have a small number
while(display > 2000)
while
{
display /= 1024;
measure++;
measure
}
// now there are two cases
// a) the number has two, three or four characters - we won't display
the digits after the comma
// b) the number has one character. This means we will have to print
a comma and the next number after
//
the digit
int number = (int) display;
result
result.append(number);
result.append(measure_chars[measure]);
result
return result.toString();
}
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// W E B - R E L A T E D
M E T H O D S
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------/**
* this converts a string into one that is compatible for being used i n
a link
lin
* with get-parameters
get-parameter
*
* @param input the inputstring
inputstrin
* @return the correct string
strin
*/
public synchronized static String httpGetString(String input)
{
input = replace(input, "%", "%25");
input = replace(input, " ", "%20");
return input;
}
//
------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// D A T A B A S E
M E T H O D S
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------/**
* this converts a date into a Oracle-compliant string including the '
's
*
* @param date a date
dat
* @return the string
strin
*/
public synchronized static String oracleDate(Date date)
{
if(date != null)
if
{
StringBuffer tmp = new StringBuffer();
tmp.append("TO_DATE('");
tmp
tmp.append(fitNumber(String.valueOf(date.getDate()), 2));
tmp
switch(date.getMonth())
switch
{
case 0:
tmp.append("-JAN-");
tmp
break;
break
case 1:
tmp.append("-FEB-");
tmp
break;
break
case 2:
tmp.append("-MAR-");
tmp
break;
break
case 3:
tmp.append("-APR-");
tmp
break;
break
case 4:
tmp.append("-MAY-");
tmp
break;
break
case 5:
tmp.append("-JUN-");
tmp
break;
break
case 6:
tmp.append("-JUL-");
tmp
break;
break
case 7:
tmp.append("-AUG-");
tmp
break;
break
case 8:
tmp.append("-SEP-");
tmp
break;
break
case 9:
tmp.append("-OCT-");
tmp
break;
break
case 10:
tmp.append("-NOV-");
tmp
break;
break
case 11:
tmp.append("-DEC-");
tmp
break;
break
}
tmp.append(String.valueOf(date.getYear() + 1900));
tmp
tmp
tmp.append("
");
tmp.append(fitNumber(String.valueOf(date.getHours()), 2));
tmp
tmp.append(":");
tmp
tmp.append(fitNumber(String.valueOf(date.getMinutes()), 2));
tmp
tmp.append(":");
tmp
tmp.append(fitNumber(String.valueOf(date.getSeconds()), 2));
tmp
tmp
tmp.append("','DD-MON-YYYY
HH24:MI:SS')");
return tmp.toString();
}
return null;
}
/**
* this converts a date into a MySQL-compliant string including the ' ' s
*
* @param date a date
dat
* @return the string
strin
*/
public synchronized static String mysqlDate(Date date)
{
if(date != null)
if
{
StringBuffer tmp = new StringBuffer();
tmp.append("'");
tmp
tmp.append(String.valueOf(date.getYear() + 1900));
tmp
tmp.append("-");
tmp
tmp.append(fitNumber(String.valueOf(date.getMonth()), 2));
tmp
tmp.append("-");
tmp
tmp.append(fitNumber(String.valueOf(date.getDate()), 2));
tmp
tmp.append(" ");
tmp
tmp
tmp.append(fitNumber(String.valueOf(date.getHours()),
2));
tmp.append(":");
tmp
tmp.append(fitNumber(String.valueOf(date.getMinutes()), 2));
tmp
tmp.append(":");
tmp
tmp.append(fitNumber(String.valueOf(date.getSeconds()), 2));
tmp
tmp.append("'");
tmp
return tmp.toString();
}
return null;
}
/**
* this is used to make sure a string is SQL complian t
*
* @param in the source string
strin
* @return SQL compliant string
strin
*/
public static String sqlString(String in)
{
String tmp = in;
if(tmp == null)
if
return "NULL";
tmp = replace(tmp, "'", "''");
tmp = replace(tmp, "´", "´´");
tmp = "'" + tmp + "'";
return tmp;
}
/**
* this is used to make sure a string is SQL compliant for lik e
*
* @param in the source string
strin
* @return SQL compliant string
strin
*/
public static String sqlLikeString(String in)
{
String tmp = nonNull(in);
tmp = replace(tmp, "'", "''");
tmp = replace(tmp, "´", "´´");
tmp = "'%" + tmp + "%'";
return tmp;
}
//
---------------------------------------------------------------------------
-----------------------//
-------------------------------------------------------------------------------------------------// S P E C I A L
T Y P E
C O N V E R S I O N
M E T H O D S
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------/**
* this little method converts boolean values to strings. Unlike th e
String.toString(boolean)
String.toString(boolean
* function it doesn't convert to "true" or "false" but to:<br >
* true -> "1"<br>
"1"<br
* false --> "0"
"0
*
* @param in the boolean value
valu
* @return the String
Strin
*/
public static String booleanToString(boolean in)
{
if(in)
if
return "1";
else
return "0";
}
/**
* this converts a string containing either "0" or "1" into th e
corresponding
correspondin
* boolean value. All other values of the string return false .
*
* @param in the String
Strin
* @return the boolean equivalent of the Strin g
*/
public static boolean stringToBoolean(String in)
{
if(removeSurroundingWhitespaces(in).equals("1"))
if
return true;
return false;
}
/**
* this creates a <code>Properties</code> object from a
whitespace/comma/semicolon
whitespace/comma/semicolo
* separated word list in a string. The values of the words are set t o
null
nul
*
* @param wordlist the word list
lis
* @return the Properties object
objec
*/
public synchronized static Properties whitespaceList(String wordlist)
{
// remove surrounding whitespaces
wordlist = removeWhitespaces(wordlist);
Properties list = new Properties();
if(empty(wordlist))
if
return null;
StringTokenizer st = new StringTokenizer(wordlist, " ;\n", false);
while(st.hasMoreTokens())
while
{
String token = st.nextToken();
list.put(token, token);
list
}
return list;
}
//
--------------------------------------------------------------------------------------------------
//
-------------------------------------------------------------------------------------------------// S U P P L E M E N T A R Y
M E T H O D S
//
-------------------------------------------------------------------------------------------------//
--------------------------------------------------------------------------------------------------
/**
* This will extract a usable String from a querystring hashtable tha t
is never null.
null
*
* @param param_name the name of the parameter to ge t
* @param q
* @return a String
Strin
*/
public static String getQueryParam(String param_name, Hashtable
querystring)
{
if(querystring == null || param_name == null)
if
return new String();
String[] many = (String[])querystring.get(param_name);
String
if(many == null)
if
return new String();
String single = many[0];
if(single == null)
if
return new String();
return single.trim();
}
public static final int SIZE_OK = 0;
public static final int MAX_EXCEEDED = 1;
public static final int MIN_EXCEEDED = 2;
/**
* This will check if the size of a String is correct.
*
* @param input the input String
Strin
* @param min the minimum length
lengt
* @param max the maximum length
lengt
* @return SIZE_OK, if the size is ok, MAX_EXCEEDED or MIN_EXCEEDED i f
not.
not
*/
public static int checkSize(String input, int min, int max)
{
if(input == null && min > 0)
if
return MIN_EXCEEDED;
if(input.length() < min)
if
return MIN_EXCEEDED;
if(input.length() > max)
if
return MAX_EXCEEDED;
return SIZE_OK;
}
public static Random random = new Random();
/**
* This method will return a String containing a random number in th e
length given.
given
*
* @param length
* @return a random number in the requested lengt h
*/
public static String randomNumber(int length)
{
StringBuffer result = new StringBuffer();
byte[] numbers = new byte[length];
byte
random.nextBytes(numbers);
random
while
while(length
> 0)
{
length--;
length
// append the char representation of this number to the buffer
String number = (new Integer(numbers[length])).toString();
result.append(number.substring(number.length() - 1));
result
}
return result.toString();
}
/**
* returns the minimum of two integer s
*
* @param i1 first number
numbe
* @param i2 second number
numbe
* @return the minimum
minimu
*/
private synchronized static int min(int i1, int i2)
{
if(i1 < i2) return i1;
if
return i2;
}
/**
* this returns how many days a month ha s
*
* @param month the month to look fo r
* @param year the year to look fo r
* @return the number of days
day
*/
public static int howManyDays(int month, int year)
{
if(month == 1 || month == 3 || month == 5 || month == 8 || month ==
if
10 || month == 12)
return 31;
if(month == 2)
if
{
if(year < 90)
if
year += 2000;
if(year < 100)
if
year += 1900;
if(year == 2000)
if
return 28;
if(year % 4 == 0)
if
return 29;
return 28;
}
return 30;
}
/**
* Returns a String containing the name of the day .
*
* @return a String containing the name of the day .
*/
public static String dayString(int day)
{
switch(day)
switch
{
case GregorianCalendar.MONDAY: return "Monday";
case GregorianCalendar.TUESDAY: return "Tuesday";
case GregorianCalendar.WEDNESDAY: return "Wednesday";
case GregorianCalendar.THURSDAY: return "Thursday";
case GregorianCalendar.FRIDAY: return "Friday";
case GregorianCalendar.SATURDAY: return "Saturday";
case GregorianCalendar.SUNDAY: return "Sunday";
}
return null;
}
protected static java.util.Date format_date = new java.util.Date();
protected static GregorianCalendar format_cal = new GregorianCalendar();
/**
* This method will convert a date that is stored in a long into a U S
formatted
formatte
* date in the form MM/DD/YYYY HH:MM.
*
* @param theTime long the date
dat
* @return the String containing the formatted date, null if the date i s
undefined
undefine
*/
public synchronized static String formatDate(long theTime)
{
format_date.setTime(theTime);
format_date
format_cal.setTime(format_date);
format_cal
StringBuffer result = new StringBuffer();
int month = format_cal.get(Calendar.MONTH) + 1;
if(month < 10)
if
result.append("0");
result
result.append(month);
result
result.append("/");
result
int date = format_cal.get(Calendar.DATE);
if
if(date
< 10)
result.append("0");
result
result.append(date);
result
result.append("/");
result
int year = format_cal.get(Calendar.YEAR);
result
result.append(year);
result.append(" ");
result
int hour = format_cal.get(Calendar.HOUR);
if
if(hour
< 10)
result.append("0");
result
result.append(hour);
result
result.append(":");
result
int minute = format_cal.get(Calendar.MINUTE);
if
if(minute
< 10)
result.append("0");
result
result.append(minute);
result
return result.toString();
}
/**
* This method sorts an array of Strings. The algorithm used is a
mergesort, a
* modified version of quicksort that works better on arrays with fixe d
size.
size
*
* @param strings the array to sor t
*/
public static void sortStrings(String[] strings)
{
if(strings == null)
if
return;
return
sortStrings(strings, 0, strings.length-1);
sortStrings
}
/**
* This method sorts an array of Strings. The algorithm used is a
mergesort, a
* modified version of quicksort that works better on arrays with fixe d
size.
size
*
* @param strings the array to sor t
* @param start the index to start a t
* @param end the index to end a t
*/
public static void sortStrings(String[] strings, int lo, int hi)
{
// do not sort one item (it's already sorted ;-))
if(lo == hi)
if
return;
return
// the length of the buffer array to sort in
int length = hi-lo+1;
// set the pivot to the middle of the array
int pivot = (lo+hi)/2;
// sort both parts left and right of the array
sortStrings(strings, lo, pivot);
sortStrings
sortStrings(strings, pivot+1, hi);
sortStrings
// now that they're sorted copy all of them into a working array
String[] working = new String[length];
String
for(int i = 0; i < length; i++)
for
working[i] = strings[lo+i];
working
// merge the two parts that have been sorted
int m1 = 0;
int m2 = pivot-lo+1;
for(int i=0; i<length; i++)
for
{
if(m2 <= hi-lo)
if
{
if(m1 <= pivot-lo)
if
{
if(working[m1].toLowerCase().compareTo(working[m2].toLowerCase()) > 0)
strings[i+lo] = working[m2++];
strings
else
strings[i+lo] = working[m1++];
strings
}
else
strings[i+lo] = working[m2++];
strings
}
else
strings[i+lo] = working[m1++];
strings
}
}
/**
* This method will treat a String so that it can be output t o
javascript without problems.
problems
*
* @param input the input String
Strin
* @return the java script compliant Strin g
*/
public static String javascriptString(String input)
{
return replace(input, "'", "\'");
}
/**
* This cuts Strings after a certain length and attaches "... "
*
* @param input the source String
Strin
* @param length the length the output String is suppoed to hav e
* @return the cut String
Strin
*/
public static String cutString(String input, int length)
{
if(input == null)
if
return null;
if(input.length() <= length)
if
return input;
return input.substring(0, length) + "...";
}
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// E M A I L
C H E C K E R
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// -- constants for
public static final
public static final
public static final
public static final
public static final
public static final
the
int
int
int
int
int
int
email checker
EMAIL_OK = 0;
EMAIL_EMPTY = 1;
EMAIL_CONTAINS_WS = 2;
EMAIL_INVALID_FORMAT = 3;
EMAIL_INVALID_CHARS = 4;
EMAIL_INVALID_TLD = 5;
/**
* Checks whether an email address is syntactically correct or not an d
returns
* the result in verbal form.
form
*
* @param email The address to check .
* @return The verbose result of the check .
*/
public synchronized static String emailVerbose(String email)
{
switch(emailCheck(email))
switch
{
case EMAIL_EMPTY:
return "No email-address was given.";
case EMAIL_CONTAINS_WS:
return "The email-address contains whitespaces.";
case EMAIL_INVALID_FORMAT:
return "The format of the email-address is invalid.";
case EMAIL_INVALID_CHARS:
return "The email-address contains invalid characters.";
case EMAIL_INVALID_TLD:
return "The top level domain of the email-address is not
valid.";
default:
default
return "The email-address is ok.";
}
}
/**
* Checks whether an email address is syntactically correct .
*
* @param email The address to check .
* @return True if the email is valid .
*/
public synchronized static boolean emailValid(String email)
{
int ok = emailCheck(email);
return ok == EMAIL_OK;
}
/**
* Checks whether an email address is syntactically correct or not an d
returns
* the result as an int constant.
constant
*
* @param email The address to check .
* @return The int result of the check .
*/
public synchronized static int emailCheck(String email)
{
// check if the string is null
if(email == null)
if
return EMAIL_EMPTY;
// make a copy of the string
String tmp = new String(email);
// remove whitespaces before and after the address
tmp = removeSurroundingWhitespaces(tmp);
// check if the string is empty now
if(tmp.length() == 0)
if
return EMAIL_EMPTY;
// check if the string contains any whitespaces
if(containsWhitespaces(tmp))
if
return EMAIL_CONTAINS_WS;
// the minimum length of all email addresses is [email protected] = 6 characters
if(tmp.length() < 6)
if
return EMAIL_INVALID_FORMAT;
// check for a @ and for characters before the @
if(tmp.indexOf("@") < 1)
if
return EMAIL_INVALID_FORMAT;
// does the string contain more than one @ ?
if(tmp.indexOf("@") != tmp.lastIndexOf("@"))
if
return EMAIL_INVALID_FORMAT;
// check whether there is at least one dot after the @
if(tmp.indexOf("@") > tmp.lastIndexOf("."))
if
return EMAIL_INVALID_FORMAT;
// are there characters between the @ and the first dot after it?
if(tmp.substring(tmp.indexOf("@")).indexOf(".") < 1)
if
return EMAIL_INVALID_FORMAT;
// are there characters between the @ and the first dot before it?
if(tmp.substring(0, tmp.indexOf("@") - 1).lastIndexOf(".") ==
if
tmp.substring(0, tmp.indexOf("@") - 1).length())
return EMAIL_INVALID_FORMAT;
// check whether the first character is a dot
if(tmp.indexOf(".") == 0)
if
return EMAIL_INVALID_FORMAT;
// check if we have at least four characters after the @ (eg [email protected])
if(tmp.substring(tmp.indexOf("@")+1).length() < 4)
if
return EMAIL_INVALID_FORMAT;
// commata are only allowed before the @
if(tmp.indexOf("@") < tmp.lastIndexOf(","))
if
return EMAIL_INVALID_CHARS;
// check for invalid characters
String invalidchars = "/\\?!'\"$&=`*+:;<>|[]";
for(int i = 0; i < tmp.length(); i++)
for
if(invalidchars.indexOf(tmp.substring(i, i+1)) != -1
if
|| tmp.charAt(i)
tmp
> 0x007F)
return EMAIL_INVALID_CHARS;
// last but not least check if the tld of ok
String valid_tld = "com;edu;gov;int;mil;net;org;";
valid_tld +=
"ad;ae;af;ag;ai;al;am;an;ao;aq;ar;as;at;au;aw;az;ba;bb;bd;be;bf;bg;bh;bi;bj
;bm;bn;bo;br;bs;bt;bv;bw;by;bz;ca;cc;cd;cf;cg;ch;ci;ck;cl;cm;cn;co;cr;cu;cv
;cx;cy;cz;de;dj;dk;dm;do;dz;ec;ee;eg;eh;er;es;es;et;fi;fj;fk;fm;fo;fr;fx;ga
;gb;gd;ge;gf;gg;gh;gi;gl;gm;gn;gp;gq;gr;gt;gu;gw;gy;hk;hm;hn;hr;ht;hu;id;ie
;il;im;in;io;iq;ir;is;it;je;jm;jo;jp;ke;kg;kh;ki;km;kn;kp;kr;kw;ky;kz;la;lb
;lc;li;lk;lr;ls;lt;lu;lv;ly;ma;mc;md;mg;mh;mk;ml;mm;mn;mo;mp;mq;mr;ms;mt;mu
;mv;mw;mx;my;mz;na;nc;ne;nf;ng;ni;nl;no;np;nr;nu;nz;om;pa;pe;pf;pg;ph;pk;pl
;pm;pn;pr;pt;pw;py;qa;re;ro;ru;rw;sa;sb;sc;sd;se;sg;sh;si;sj;sk;sl;sm;sn;so
;sr;st;su;sv;sy;sz;tc;td;tf;tg;th;tj;tk;tm;tn;to;tp;tr;tt;tv;tw;tz;ua;uk;ug
;um;us;uy;uz;va;vc;ve;vg;vi;vn;vu;wf;ws;ye;yt;yu;za;zm;zr;zw";
// get the characters after the last dot
String tld = tmp.substring(tmp.lastIndexOf(".") + 1);
// check for the length of the tld
if(tld.length() < 2)
if
return EMAIL_INVALID_TLD;
// check if it's valid
if(valid_tld.indexOf(tld.toLowerCase()) == -1)
if
return EMAIL_INVALID_TLD;
return EMAIL_OK;
}
//
-------------------------------------------------------------------------------------------------//
-------------------------------------------------------------------------------------------------// F I L E
R E L A T E D
//
-------------------------------------------------------------------------------------------------//
--------------------------------------------------------------------------------------------------
/**
* This method will remove this folder and all its subfolders .
* @parameter File directory to delet e
* @return true if the action completed successfull y
*/
public static boolean recursiveDelete(File rotten)
{
// if this is a file just delete
if(!rotten.isDirectory())
if
return rotten.delete();
boolean success = true;
;
String
String[]
nodes = rotten.list();
for(int i=0; i<nodes.length; i++)
for
{
File file = new File(rotten.getPath() + "/" + nodes[i]);
if(file != null)
if
success = success && recursiveDelete(file);
if(!success)
if
break;
break
}
success = success && rotten.delete();
return success;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.tools.TextFiles
java.lang.Object
|
+----mm.tools.TextFiles
public class TextFiles
extends java.lang.Object
this class offers some file operations
Author:
Stefan Zier
TextFiles()
get(String)
this method reads a textfile from the given path.
TextFiles
public TextFiles()
get
public static java.lang.String get(java.lang.String path)
this method reads a textfile from the given path. If there is a error
it only returns null.
Parameters:
path - the path to read from
Returns:
the string
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.tools;
import
import
import
import
java.io.FileReader;
java.io.FileNotFoundException;
java.io.IOException;
java.util.Hashtable;
/**
* this class offers some file operation s
*
* @author Stefan Zier
Zie
* @created 12/15/98 - last modified 12/15/9 8
*/
public class TextFiles
{
protected static Hashtable textfiles = null;
/**
* this method reads a textfile from the given path. If there is a erro r
it
* only returns null.
*
* @param path the path to read fro m
* @return the string
strin
*/
public static String get(String path)
{
if(path == null)
if
return new String();
String tmp = new String();
try
{
FileReader fr = new FileReader(path);
while(!fr.ready())
while
{}
int offset = 0;
char
char[]
ch = new char[1024];
while(offset != -1)
while
{
offset = fr.read(ch);
if(offset != -1)
if
tmp += String.valueOf(ch, 0, offset);
}
fr.close();
fr
}
catch(IOException io) {System.out.println("! getTextFileNoCache threw
catch
Exception reading \"" + path + "\"");}
return tmp;
}
}
h.) mm.webserver.servlets
Dieses Package enthält Servlets.
Klasse
RessourceServlet
StatusCheck
Bedeutung
Das Servlet von dem alle anderen Servlets
erben. Verwaltet die Ressourcen.
Überprüft den Status der Jini-Dienste
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class
mm.webserver.servlets.RessourceServlet
mm.webserver.servlets.RessourceServlet
public abstract class RessourceServlet
Von diesem Servlet sollten alle Servlets erben. Es verwaltet gemeinsame
Ressourcen wie den Session Manager und die RMI Verbindungen zu den Jini
Services.
Version:
1.0
Author:
Stefan Zier
configfile_location
RessourceServlet()
_service(HttpServletRequest, HttpServletResponse)
this method is defined in the JSP standard and is called by the servlets
service() method to process a request.
getServletConfig()
this method is defined in the JSP standard and has to return the
servlet configuration.
init(ServletConfig)
Dies ist die Hauptinitmethode des Webservers.
loadConfigFile()
lädt die Konfigurationsdatei
loadSessionManager()
lädt den Session Manager
service(ServletRequest, ServletResponse)
this method is the service method derived from the servlet API.
configfile_location
public static final java.lang.String configfile_location
RessourceServlet
public RessourceServlet()
loadConfigFile
public void loadConfigFile() throws javax.servlet.ServletException
lädt die Konfigurationsdatei
loadSessionManager
public void loadSessionManager() throws javax.servlet.ServletException
lädt den Session Manager
init
public void init(javax.servlet.ServletConfig config) throws javax.servlet.ServletException
Dies ist die Hauptinitmethode des Webservers. Alle gemeinsam
genutzten Ressourcen werden hier initialisiert. Damit sie pro Webserver nur
ein mal vorhanden sein müssen werden sie über den Servlet Context
anderen Instanzen zur Verfügung gestellt.
service
public void service(javax.servlet.ServletRequest req,
javax.servlet.ServletResponse res) throws javax.servlet.ServletExcepti
this method is the service method derived from the servlet API. it is
called for evert request that the server needs to answer. It is _required_ to
call the _jspService() method from this method. Subclasses but not the JSP
page may override it.
_service
public abstract void _service(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws java
this method is defined in the JSP standard and is called by the
servlets service() method to process a request.
Parameters:
request - the HttpServletRequest object
response - the HttpServletResponse object
getServletConfig
public final javax.servlet.ServletConfig getServletConfig()
this method is defined in the JSP standard and has to return the
servlet configuration.
Returns:
the ServletConfig object
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.webserver.servlets;
// Java Core imports
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.sql.SQLException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.rmi.RemoteException;
// Java Servlet imports
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
// Project imports
import mm.webserver.sessions.Session;
import mm.webserver.sessions.SessionManager;
import mm.webserver.sessions.SessionManagerImpl;
import mm.jini.ServiceController;
// Project service imports
import mm.services.files.FileServer;
import mm.services.game.GameServer;
import mm.services.mailer.MailServer;
import mm.services.msgboard.MessageBoardServer;
import mm.services.chat.Chat;
// Project tool imports
import mm.tools.ConfigFile;
import mm.tools.Static;
/**
* Von diesem Servlet sollten alle Servlets erben. Es verwaltet gemeinsam e
Ressourcen wie
* den Session Manager und die RMI Verbindungen zu den Jini Services .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public abstract class RessourceServlet extends HttpServlet
{
// -- gemeinsame Ressourcen
// Die Konfigurationsdatei
protected ConfigFile configfile = null;
// Die Serlvet Configuration
protected ServletConfig config = null;
// Der session manager
protected SessionManager session_manager = null;
// Der Jini Service Controller
protected ServiceController service_controller = null;
// Die Basis-URL der Webseite
protected String baseurl = null;
// Der servlet context
ServletContext context = null;
// Pfad zum Konfigurationsfile
public final static String configfile_location =
"/export/home/source/mm/webserver/webserver.properties";
// Konstanten für Service-Klassennamen
protected final String FILE_SERVER = "mm.services.files.FileServer";
protected final String MSGBOARD_SERVER =
"mm.services.msgboard.MessageBoardServer";
protected final String MAIL_SERVER = "mm.services.mailer.MailServer";
protected final String GAME_SERVER = "mm.services.game.GameServer";
protected final String CHAT_SERVER = "mm.services.chat.Chat";
// Standard-Sprache
protected final String DEFAULT_LANGUAGE = "de";
protected final boolean debug = true;
/**
* lädt die Konfigurationsdatei
Konfigurationsdate
*/
public void loadConfigFile()
throws ServletException
{
try
{
configfile = new ConfigFile(configfile_location);
}
catch(java.io.IOException io)
catch
{
forwardThrowable("mm: error loading config file", io);
forwardThrowable
}
}
/**
* lädt den Session Manager
Manage
*/
public void loadSessionManager()
throws ServletException
{
try
{
// Sesion Manager mit timeout 10 Minuten erstellen
session_manager = new SessionManagerImpl(600);
}
catch(IllegalArgumentException iae)
catch
{
forwardThrowable("mm: error instantiating session manager", iae);
forwardThrowable
}
}
/**
* Dies ist die Hauptinitmethode des Webservers. Alle gemeinsa m
genutzten Ressourcen werden
werde
* hier initialisiert. Damit sie pro Webserver nur ein mal vorhande n
sein müssen werden sie
* über den Servlet Context anderen Instanzen zur Verfügung gestellt.
*/
public void init(ServletConfig config)
throws ServletException
{
// Servlet Config speichern
this.config = config;
this
// servlet context holen
context = config.getServletContext();
// Konfigurationsdatei laden
configfile =
(ConfigFile)context.getAttribute("webserver.properties");
if(configfile == null)
if
{
loadConfigFile();
loadConfigFile
// publizieren
context.setAttribute("webserver.properties", configfile);
context
}
// this is the session management class
session_manager =
(SessionManager)context.getAttribute("mm.webserver.sessions.SessionManager"
);
if
if(session_manager
== null)
{
loadSessionManager();
loadSessionManager
// publizieren
context.setAttribute("mm.webserver.sessions.SessionManager",
context
session_manager);
}
// baseurl setzen
baseurl = configfile.get("server.baseurl");
service_controller =
(ServiceController)context.getAttribute("mm.webserver.jini.ServiceControlle
r");
if(service_controller == null)
if
{
try
{
service_controller = new ServiceController();
// wir suchen klassen x,y und y
service_controller.addSearchClass(FILE_SERVER);
service_controller
service_controller.addSearchClass(CHAT_SERVER);
service_controller
service_controller.addSearchClass(MSGBOARD_SERVER);
service_controller
service_controller.addSearchClass(MAIL_SERVER);
service_controller
service_controller.addSearchClass(GAME_SERVER);
service_controller
}
catch(IOException ioe)
catch
{
throw new ServletException("mm: error while instantiation
the service controller", ioe);
}
}
}
/**
* this method should be used to forward exceptions to the JVM. It als o
prints the
* stacktrace of the exception onto the screen. All JSP pages should us e
this mechanism
* to handle exceptions.
exceptions
*
* @param text the text to display on the screen and for the newl y
generated ServletException
ServletExceptio
* @param throwable the Throwable object to forwar d
*/
protected void forwardThrowable(String text, Throwable throwable)
throws ServletException
{
//write the exception on the screen if debug is on
throwable
throwable.printStackTrace(System.out);
// write the exception to the log file
context
context.log(text, throwable);
// forward the exception to the servlet engine
throw new ServletException(text, throwable);
}
/**
* this method is the service method derived from the servlet API. it i s
* called for evert request that the server needs to answer. It is
* _required_ to call the _jspService() method from this method.
* Subclasses but not the JSP page may override it .
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
try
{
// get the querystring
String query_string = request.getQueryString();
Hashtable querystring = null;
// parse it to get the session id
if(!Static.empty(query_string))
if
{
querystring = HttpUtils.parseQueryString(query_string);
// save the Hashtable for latter use
if(querystring != null)
if
request.setAttribute("querystring", querystring);
request
}
String sid = null;
// look up the session id
if(querystring != null)
if
{
String[] sids = (String[]) querystring.get("sid");
String
if(sids !=null)
if
sid = sids[0];
// get the session
if(!Static.empty(sid))
if
{
Session session = session_manager.find(sid);
if(session != null)
if
{
request.setAttribute("sid", sid);
request
request.setAttribute("session", session);
request
}
}
}
// finally do the JSP page processing...
_service(request, response);
_service
}
catch(Throwable se)
catch
{
// Stacktrace auf die Fehlerkonsolre schreiben
System.err.println("mm: " + this.getClass().getName() +
System
".service() threw Exception:");
se.printStackTrace(System.err);
se
// ggf. Stacktrace auf den Webbrowser schreiben
res.setContentType("text/html");
res
PrintWriter out = res.getWriter();
if(debug)
if
{
out.println("<html><head><title>MM ERROR</title></head><body
out
bgcolor=\"#FFFFFF\">");
out.println("<h3>JSP Page exception in class " +
out
this.getClass().getName() + "</h3><font size=\"-1\"><tt>");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
se.printStackTrace(pw);
se
String se_html = Static.replace(sw.toString(), "\n", "<br>\n");
out
out.println(se_html);
out.println("</tt></font></body></html>");
out
}
else
{
out.println("Müll");
out
}
}
}
/**
* this method is defined in the JSP standard and is called by th e
servlets
servlet
* service() method to process a request .
*
* @param request the HttpServletRequest objec t
* @param response the HttpServletResponse objec t
*/
public abstract void _service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
/**
* this method is defined in the JSP standard and has to return th e
servlet
servle
* configuration.
configuration
*
* @return the ServletConfig object
objec
*/
final public ServletConfig getServletConfig()
{
return config;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.webserver.servlets.StatusCheck
mm.webserver.servlets.RessourceServlet
|
+----mm.webserver.servlets.StatusCheck
public class StatusCheck
extends RessourceServlet
Diese Klasse initialisiert alle shared Ressources der JspSuperClass und
zeigt den Status der Services an.
Version:
1.0
Author:
Stefan Zier
StatusCheck()
_service(HttpServletRequest, HttpServletResponse)
Gibt den Status der Services aus.
checkService(String, BlockList)
Schreibt eine Zeile der Statustabelle
StatusCheck
public StatusCheck()
_service
public void _service(javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse res)
Gibt den Status der Services aus.
Parameters:
req - der Request
res - die Response
Overrides:
_service in class RessourceServlet
checkService
public void checkService(java.lang.String servicename,
com.zier.fasthtml.tools.BlockList blocklist)
Schreibt eine Zeile der Statustabelle
Parameters:
servicename - der Service Name der gecheckt werden soll
out - der PrintWriter in den das HTML geschrieben werden soll
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.webserver.servlets;
// Java core imports
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.rmi.RemoteException;
// Servlet extension imports
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Project imports
import mm.tools.AliveCheckable;
import mm.tools.Static;
// FastHtml imports
import com.zier.fasthtml.tools.BlockList;
import com.zier.fasthtml.Page;
/**
* Diese Klasse initialisiert alle shared Ressources der JspSuperClass
* und zeigt den Status der Services an.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
* @deprecated Das RessourceServlet ist aktuell
aktuel
*/
public class StatusCheck extends RessourceServlet
{
/**
* Gibt den Status der Services aus .
*
* @param req der Request
Reques
* @param res die Response
Respons
*/
public void _service(HttpServletRequest req, HttpServletResponse res)
{
/* try
{
res.setContentType("text/html");
res.setContentType("text/html")
checkService(MAIL_SERVER, out);
out)
checkService(FILE_SERVER, out);
out)
checkService(MSGBOARD_SERVER, out);
out)
checkService(CHAT_SERVER, out);
out)
checkService(GAME_SERVER, out);
out)
out.println("</table>");
out.println("</table>")
}
catch(IOException ioe)
ioe
{
}
*/
}
/**
* Schreibt eine Zeile der Statustabelle
Statustabell
*
* @param servicename der Service Name der gecheckt werden sol l
* @param out der PrintWriter in den das HTML geschrieben werden sol l
*/
public void checkService(String servicename, BlockList blocklist)
{
/*
blocklist.set("servicename", servicename);
blocklist
AliveCheckable ac = (AliveCheckable)
(AliveCheckable
service_controller.getService(servicename)
service_controller.getService(servicename);
if(ac == null)
null
out.println(font_red + "null");
"null")
else
els
{
try
tr
{
if(ac.isAlive())
if(ac.isAlive()
{
blocklist.set("color", "#FFFFFF");
"#FFFFFF")
blocklist.set("status", "OK");
"OK")
}
else
els
{
blocklist.set("color", "#FF0000");
"#FF0000")
blocklist.set("status", "down");
"down")
}
}
catch(RemoteException re)
re
{
blocklist.set("color", "#FF0000");
"#FF0000")
blocklist.set("status", "RemoteException:<br><tt>");
"RemoteException:<br><tt>")
// Exception Stacktrace in HTML umwandeln (CR/LFs)
(CR/LFs
StringWriter sw = new StringWriter();
StringWriter()
PrintWriter pw = new PrintWriter(sw);
PrintWriter(sw)
re.printStackTrace(pw);
re.printStackTrace(pw)
out.println(Static.replace(sw.toString(), "\n", "<br>"));
"<br>"))
out.println("</tt>");
out.println("</tt>")
}
}
out.println("</font></td></tr>"); */
}
}
i.) mm. webserver.sessions
Dieses Package enthält Klassen, die für das Session Management zuständig sind. Wir
entschieden uns, ein eigenes Session Management zu entwickeln, obwohl Servlets diese
Funktionalität bereits bieten. So ist es möglich, einen verteilten Session-ManagementMechanismus über mehrere Webserver hinweg zu implementieren.
Klasse
Session
SessionManager
SessionManagerImpl
Bedeutung
Eine Sitzung
Interface zum Session Manager
Eine
Implementation
eines
Session
Managers für den Standalonebetrieb
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class mm.webserver.sessions.Session
java.lang.Object
|
+----mm.webserver.sessions.Session
public class Session
extends java.lang.Object
Diese Klasse stellt eine Sitzung dar. Sie kann beliebige Objekte die mit der
Sitzung in Verbindung stehen unter einem Schlüsselwert abspeichern.
Version:
1.0
Author:
Stefan Zier
Session(String)
Konstruktor.
create()
Creator Methode.
getAttribute(String)
Liest ein Attribut.
getSessionId()
Accessor für die Session ID
outdated(int)
Prüft, ob die Session veraltet ist.
setAttribute(String, Object)
Setzt ein Attribut.
touch()
Aktualisiert die Zeit an dem das Objekt zuletzt aktualisiert wurde.
Session
public Session(java.lang.String sid)
Konstruktor. Dient dazu eine Session zu erzeugen.
Parameters:
sid - die Session ID
create
public static Session create()
Creator Methode. Diese Methode generiert automatisch ein Session
und erzeugt auch eine Session ID.
Returns:
ein neues Session Objekt
setAttribute
public void setAttribute(java.lang.String key,
java.lang.Object value)
Setzt ein Attribut.
Parameters:
key - der Name des Attributes
value - das Objekt
getAttribute
public java.lang.Object getAttribute(java.lang.String key)
Liest ein Attribut.
Parameters:
key - der Name des Attributes
Returns:
das Attribut
getSessionId
public java.lang.String getSessionId()
Accessor für die Session ID
Returns:
die Session ID
touch
public void touch()
Aktualisiert die Zeit an dem das Objekt zuletzt aktualisiert wurde.
outdated
public boolean outdated(int timeout)
Prüft, ob die Session veraltet ist.
Parameters:
timeout - die Zeit nach der eine Session veraltet sein soll in
sekunden
Returns:
true wenn die Session veraltet ist.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.webserver.sessions;
import
import
import
import
java.util.Hashtable;
java.util.Date;
java.util.GregorianCalendar;
java.util.Random;
/**
* Diese Klasse stellt eine Sitzung dar. Sie kann beliebige Objekte die mi t
der Sitzung in
* Verbindung stehen unter einem Schlüsselwert abspeichern .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class Session
{
private String sid = null;
private Hashtable attributes = null;
private Date last_touched = null;
private static Random random = new Random();
/**
* Konstruktor. Dient dazu eine Session zu erzeugen .
*
* @param sid die Session ID
I
*/
public Session(String sid)
{
// Session ID Speichern
this.sid = sid;
this
// Hashtable anlegen
attributes = new Hashtable();
// last_touched initialisieren
last_touched = new Date();
}
/**
* Creator Methode. Diese Methode generiert automatisch ein Session un d
erzeugt auch eine
ein
* Session ID.
ID
*
* @return ein neues Session Objekt
Objek
*/
public static Session create()
{
// eine Session ID generieren
StringBuffer sid = new StringBuffer();
byte[] numbers = new byte[13];
byte
String sid_string = null;
random.nextBytes(numbers);
random
int count = 0;
while
while(count
< 13)
{
// append the char representation of this number to the buffer
String number = (new Integer(numbers[count])).toString();
sid.append(number.substring(number.length() - 1));
sid
count++;
count
// the dashes
if(count == 3 || count == 8)
if
sid.append("-");
sid
}
sid_string = sid.toString();
return new Session(sid_string);
}
/**
* Setzt ein Attribut.
Attribut
*
* @param key der Name des Attribute s
* @param value das Objekt
Objek
*/
public void setAttribute(String key, Object value)
{
attributes.put(key, value);
attributes
}
/**
* Liest ein Attribut.
Attribut
*
* @param key der Name des Attribute s
* @return das Attribut
Attribu
*/
public Object getAttribute(String key)
{
return attributes.get(key);
}
/**
* Accessor für die Session ID
I
*
* @return die Session ID
I
*/
public String getSessionId()
{
return sid;
}
/**
* Aktualisiert die Zeit an dem das Objekt zuletzt aktualisiert wurde .
*/
public void touch()
{
last_touched = new Date();
}
/**
* Prüft, ob die Session veraltet ist .
*
* @param timeout die Zeit nach der eine Session veraltet sein soll i n
sekunden
sekunde
* @return true wenn die Session veraltet ist .
*/
public boolean outdated(int timeout)
{
// Kalender auf aktuelle Zeit setzen
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(new Date());
gc
// die Zeit des Kalenders um den Timeout zurücksetzen
gc.add(gc.SECOND, 0 - timeout);
gc
// anderen Kalender auf letzten Touch setzen
GregorianCalendar last = new GregorianCalendar();
last.setTime(last_touched);
last
// vergleichen: ist jetzt-timeout > last touched ist die Session
veraltet.
if(gc.after(last))
if
return true;
return false;
}
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Interface
mm.webserver.sessions.SessionManager
public interface SessionManager
Das Interface zu einem Session Manager. So ist es Möglich später ggf. statt
des lokalen einen RMI-Session Manager einzusetzen, der mehrere
Webserver ermöglicht.
Version:
1.0
Author:
Stefan Zier
add(Session)
fügt eine neue Session hinzu.
find(String)
Sucht nach eine Session.
add
public void add(Session session)
fügt eine neue Session hinzu.
Parameters:
session - die neue Session
find
public Session find(java.lang.String sid)
Sucht nach eine Session. Muss die Session auch touchen.
Parameters:
sid - die Session Id
Returns:
das Session Objekt oder null wenn die Session nicht mehr
existiert.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.webserver.sessions;
/**
* Das Interface zu einem Session Manager. So ist es Möglich später ggf .
statt des lokalen
lokale
* einen RMI-Session Manager einzusetzen, der mehrere Webserver ermöglicht .
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public interface SessionManager
{
/**
* fügt eine neue Session hinzu.
hinzu
*
* @param session die neue Session
Sessio
*/
public void add(Session session);
/**
* Sucht nach eine Session. Muss die Session auch touchen.
*
* @param sid die Session Id
I
* @return das Session Objekt oder null wenn die Session nicht meh r
existiert.
existiert
*/
public Session find(String sid);
}
All Packages
Class Hierarchy
This Package
Previous
Next
Index
Class
mm.webserver.sessions.SessionManagerImpl
java.lang.Object
|
+----mm.webserver.sessions.SessionManagerImpl
public class SessionManagerImpl
extends java.lang.Object
implements SessionManager
Diese Klasse ist ein Session Manager. Sie verwaltet Sitzungen. Eine Sitzung
wird durch das Session-Objekt repräsentiert. Nach einer gegebenen
Zeitspanne ohne Seitenabruf ist eine Session hinfällig und wird gelöscht.
Version:
1.0
Author:
Stefan Zier
SessionManagerImpl(int)
Konstruktor.
add(Session)
fügt eine neue Session hinzu.
find(String)
Sucht nach eine Session.
SessionManagerImpl
public SessionManagerImpl(int timeout)
Konstruktor.
Parameters:
timeout
- die Zeit in Sekunden nach der eine Session gelöscht wird
add
public void add(Session session)
fügt eine neue Session hinzu.
Parameters:
session - die neue Session
find
public Session find(java.lang.String sid)
Sucht nach eine Session. Muss die Session auch touchen.
Parameters:
sid - die Session Id
Returns:
das Session Objekt oder null wenn die Session nicht mehr
existiert.
All Packages
Class Hierarchy
This Package
Previous
Next
Index
package mm.webserver.sessions;
import java.util.Hashtable;
/**
* Diese Klasse ist ein Session Manager. Sie verwaltet Sitzungen. Ein e
Sitzung wird durch
durc
* das Session-Objekt repräsentiert. Nach einer gegebenen Zeitspanne ohn e
Seitenabruf ist
is
* eine Session hinfällig und wird gelöscht.
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
public class SessionManagerImpl implements SessionManager
{
private CleanerThread cleaner = null;
private Hashtable sessions = null;
/**
* Konstruktor.
*
* @param timeout die Zeit in Sekunden nach der eine Session gelösch t
wird
wir
*/
public SessionManagerImpl(int timeout)
{
// Sessionliste erzeugen
sessions = new Hashtable();
// CleanerThread starten
cleaner = new CleanerThread(timeout);
cleaner.start();
cleaner
}
/**
* Interne Klasse, die die Sessionliste nach veralteten Einträge n
durchkämmt.
durchkämmt
*
* @author Stefan Zier
Zie
* @version 1.0
1.
*/
private class CleanerThread extends Thread
{
private long timeout = -1;
/**
* Konstruktor.
Konstruktor
*
* @param timeout die Zeit in Sekunden nach der eine Session gelösch t
wird
wir
*/
public CleanerThread(int timeout)
{
// Timeout speichern
this.timeout = timeout;
this
// Korrektheit überprüfen
if(timeout <= 0)
if
throw new IllegalArgumentException("mm: timeout must be bigger
than 0 !");
}
/**
* Der Inhalt des Threads.
*/
public void run()
{
try
{
// Pro Minute einmal die Session Liste durchgehen
sleep(60000);
sleep
}
catch(InterruptedException e)
catch
{}
}
}
/**
* fügt eine neue Session hinzu.
hinzu
*
* @param session die neue Session
Sessio
*/
public void add(Session session)
{
if(session == null)
if
return;
return
sessions.put(session.getSessionId(), session);
sessions
}
/**
* Sucht nach eine Session. Muss die Session auch touchen.
*
* @param sid die Session Id
I
* @return das Session Objekt oder null wenn die Session nicht meh r
existiert.
existiert
*/
public Session find(String sid)
{
// Session lesen
Session tmp = (Session)sessions.get(sid);
// ggf. touchen
if(tmp != null)
if
tmp.touch();
tmp
return tmp;
}
}
Herunterladen