Neuerungen der J2SE 1.4 zur Oberflächenanbindung von Dateisystemen

Zeig' mir wer Du bist

Karsten Lentzsch

Java mangelte es bisher an einfachen Zugriffen auf betriebssystemnahe Dateieigenschaften. So unterscheiden etwa die Datei-Icons des bisherigen JFileChoosers ein Diskettenlaufwerk nicht von einer Festplatte oder einem CD-ROM-Laufwerk. Das wird mit der Java 2 Standard Edition 1.4 besser. Dieser Beitrag erläutert die neuen Fähigkeiten zur Anbindung eines Dateisystems an eine Java-Oberfläche und demonstriert sie am Beispiel eines Dialogs zur Verzeichnisauswahl.

Als Plattform-unabhängige Umgebung ist Java naturgemäß nicht so eng an betriebssystemspezifische Fähigkeiten angebunden wie native Anwendungen. Das stört bei serverseitiger Programmierung nur selten. Bei der Client-GUI-Programmierung kann es schnell dazu führen, dass Java-Oberflächen altbacken aussehen, sich ungewohnt verhalten und einen im Vergleich zur nativen Konkurrenz eingeschränkten Funktionsumfang bieten. Wer z. B. einen anwendungsspezifisch angepassten, aber zeitgemäßen und möglichst standardisierten Dialog zum Öffnen einer Datei anbieten möchte, stößt schnell an die Grenzen der Java-APIs. Zwar bietet Java bereits seit dem JDK 1.0 über die Klasse java.awt.FileDialog eine Anbindung an den Plattform-spezifischen Standarddialog zum Öffnen einer Datei. Dieser lässt sich aber weder anpassen noch in eigene Rahmen oder Dialoge einbetten. Außerdem sind dessen Dateinamenfilter nicht implementiert und lassen sich auch nur schwer implementieren [1]. Die Swing-Klasse JFileChooser ist dagegen anpassbar, aber sie hinkte bisher im Aussehen und in der Funktionalität weit hinter vergleichbaren nativen Dialogen hinterher. Sun hat sich dieser Situation mit der J2SE 1.4 angenommen und ist zwei besonders wichtige Schwachpunkte angegangen: die häufig verwendete Dateiauswahl zum Öffnen, Speichern, usw. ist verbessert worden und die im Client-Bereich am weitesten verbreitete Plattform MS Windows wird deutlich besser unterstützt [2]. Dazu hat Sun den JFileChooser und seine UI-Delegates überarbeitet und die darunter liegende Dateisystemzugriffsschicht der Klasse FileSystemView aus dem Paket javax.swing.filechooser erweitert. Deren Windows-Implementierung liefert ab der 1.4 die Betriebssystem-Datei-Icons, beherrscht die unter Windows gewohnten Shell-Ordner Desktop, Eigene Dateien, usw. und bietet – soweit vorhanden – einen Direktzugriff auf die Netzwerkhierarchie.
Man beachte, dass die Erweiterungen an FileSystemView plattformübergreifend angelegt sind. Sun bietet damit Java-Lizenznehmern die Möglichkeit, eigene Implementierungen z. B. für OS/2, BeOS, etc. einzusetzen. Allerdings ist die bisher einzige öffentlich verfügbare FileSystemView-Implementierung, die deren Fähigkeiten in Betriebssystemaufrufe umsetzt, diejenige für Windows-Dateisysteme. Deshalb beziehen sich die meisten Beispiele in diesem Artikel auf MS Windows.
Ohne weiteres Zutun werden Anwendungen, die einen JFileChooser verwenden, unter der J2SE 1.4 von diesen Neuerungen profitieren. Aber auch in eigenen Komponenten kann man die FileSystemView-Klasse sinnvoll nutzen, etwa indem man beim Rendern der Zellen eines Verzeichnisbaums oder einer Dateiliste vorhandene Datei-Icons verwendet. Dieser Artikel soll das hierfür nötige Wissen vermitteln. Er basiert auf den Informationen und dem Quellcode zur zweiten öffentlichen Beta-Version der J2SE 1.4 und ist überwiegend auf Swing-basierte Anwendungen ausgerichtet. Zunächst werden die wesentlichen Java-Dateizugriffsschichten vorgestellt. Danach werden die Neuerungen der J2SE 1.4 präsentiert, die schließlich im Rahmen eines Verzeichnisauswahldialogs demonstriert werden.

Dateisystemzugriffe zusammengefasst

Grundlegende Zugriffe auf Dateisysteme bietet Java über die Klasse java.io.File. Die wiederum nutzt als Abstraktion eines Dateisystems java.io.FileSystem. Diese Klassen ermöglichen unter anderem die Bearbeitung von Dateinamen und -pfaden, das Anlegen und Entfernen von Dateien und Verzeichnissen sowie den Zugriff auf Dateiattribute für Lese- und Schreibrechte.
Um Betriebssystemeigenheiten bei der Präsentation eines Dateisystems zu berücksichtigen, verwendet der JFileChooser als Schnittstelle zum Dateisystem die Klassen FileSystemView und FileView aus dem Paket javax.swing.filechooser. Dadurch sollen Systemdateien oder Systemordner genau wie in nativen Dateiauswahldialogen von der Anzeige und Auswahl ausgeschlossen werden können – unter Windows z. B. C:pagefile.sys oder C:WinntProfileskarstenhistoryHistory.IE5. Des Weiteren kann abweichend von der konkreten Dateisystemstruktur eine andere Hierarchie präsentiert werden, etwa unter Windows die gewohnte Struktur der sogenannten Shell-Ordner mit Desktop als Wurzel, darunter die Kinder Eigene Dateien, Arbeitsplatz und Netzwerkumgebung und erst unter Arbeitsplatz die von java.io.File.listRoots() gelieferten Wurzeln des Dateisystems. Mit einer solchen Präsentationshierarchie geht auch die eindeutige Zuordnung einer Datei unter ein Parent-Verzeichnis verloren. Z. B. ist der Ordner Eigene Dateien sowohl unter Desktop als auch in einem benutzerspezifischen Ordner enthalten.
Die Klasse FileView bietet den Zugriff auf oberflächenbezogene Eigenschaften einer Datei. Die FileView-Implementierungen der JFileChooser-UI-Delegates können diese Klasse so implementieren, dass zu jeder Datei das zum Look passende Icon mit Beschreibung und Typbeschreibung geliefert wird. Alternativ kann man einem JFileChooser eine Benutzer-definierte FileView-Implementierung setzen.
Ein Dreigespann aus FileChooserUI, FileSystemView und FileView ist damit prinzipiell in der Lage, zu einem Look&Feel, Betriebssystem und Dateisystem eine den nativen Dateidialogen vergleichbare Lösung zu bieten. Wer eine solche Lösung mit Java 1.3 implementieren möchte, kann für die FileView-Implementierung
z. B. auf die Dateisystemerweiterungen JConfig zurückgreifen [3].

Die Neuerungen der J2SE 1.4

Im Zuge vieler kleiner Verbesserungen für die Java-Oberflächenentwicklung bringt Sun mit der J2SE 1.4 insbesondere einen kräftig überarbeiteten Windows-Look&Feel. Darunter fällt auch die Aktualisierung des WindowsFileChooserUI mit seiner an verschiedene Windows-Versionen angepassten Gestaltung, die hier aber nicht weiter behandelt werden soll. Die oben erwähnten Möglichkeiten zur betriebssystemnahen Präsentation eines Dateisystem werden – zumindest für Windows – durch die in der 1.4 enthaltenen Implementierungen auch umgesetzt. Dazu hat Sun der Klasse FileSystemView ein paar public-Methoden zugefügt. Die Standardimplementierungen dieser Methoden verwenden die neu eingeführten AWT-ShellFolder-Klassen des Pakets sun.awt.shell um an plattformspezifische Informationen zu gelangen. Dadurch bietet sich wiederum einer Plattformnahen FileView-Implementierung die Möglichkeit, Plattform-Informationen zu einer Datei direkt über FileSystemView zu ermitteln. Natürlich sind auch einige Erweiterungswünsche unerfüllt geblieben, etwa die Möglichkeit, plattformunabhängig den freien Platz auf einer Festplatte zu ermitteln [4].

Abb. 1: Der Verzeichnisauswahldialog unter Windows 2000

In diesem Abschnitt werden die mit der 1.4 eingeführten Methoden der Klasse FileSystemView vorgestellt. Dabei wird die intendierte Bedeutung angegeben. Ob eine konkrete Implementierung das gewünschte Ergebnis liefert oder liefern kann ist zum Teil plattformabhängig.
#isTraversable(File) liefert, ob ein Verzeichnis traversiert werden kann oder nicht. Das kann verwendet werden, um das Navigieren in Verbunddokumenten, die als Verzeichnisbaum abgelegt sind, zu verhindern. #getSystemDisplayName(File) liefert zu einer Datei, einem Verzeichnis oder Ordner den Namen, den auch der Betriebssystem-Datei-Browser liefert. Im Beispiel aus Abpictureung 1 ist das z. B. CD (G:) für das Verzeichnis G:. #getSystemTypeDescription(File) liefert die vom nativen Dateidialog verwendete Dateitypbeschreibung. Unter Windows wird der Desktop-Ordner mit Desktop beschrieben. #getSystemIcon(File) liefert das von der Plattform gewohnte Datei-Icon. In Abpictureung 1 z. B. das CD-ROM-Symbol für G:. #isParent(File folder, File file) antwortet, ob folder ein Verzeichnis oder Spezialordner ist, der file enthält. Im Beispiel ist das für das Paar Desktop und Eigene Dateien erfüllt. #getChild(File, String) behandelt als Erweiterung zu File(File, String) noch den Sonderfall, dass Vater und Kind Spezialordner sind. #isFileSystem(File) liefert, ob die Datei eine echte Datei oder einen Spezialordner wie Desktop repräsentiert. #isFileSystemRoot(File), #isDrive(File), #isFloppyDrive(File) und #isComputerNode(File) testen und liefern, ob die Datei eine Dateisystemwurzel, ein Diskettenlaufwerk bzw. so etwas wie Arbeitsplatz unter Windows darstellt.
Neben diesen Methoden nutzen einige JFileChooser-UIs direkt ein paar Fähigkeiten der Klasse sun.awt.shell.ShellFolder, z. B. über die Aufrufe get(„fileChooserComboBoxFolders“), get(„fileChooserDefaultFolder“), sowie get(„fileChooserShortcutPanelFolders“).

Ein Verzeichnisauswahldialog

Hier wird das oben vorgestellte API am Beispiel eines Dialog zur Verzeichnisauswahl demonstriert. Anders als der JFileChooser soll unser Dialog die Dateistruktur als Baum anzeigen (siehe Abb.1). Zur Vereinfachung haben wir auf eine Internationalisierung, auf jegliche Look-abhängige Änderung der Gestaltung, sowie auf Benutzer-definierbare FileSystemView-Implementierungen und ganz auf den Einsatz einer FileView-Implementierung verzichtet.
Die Klasse DirectoryTreeNode ist die verwendete TreeNode-Implementierung zur Präsentation der Baumstruktur eines Dateisystems. Vor allen Zugriffen auf die Kinder eines Knoten wird sichergestellt, dass die Kinder geladen sind. Das bedeutet hier, dass zu einem gegebenen FileSystemView und Verzeichnis zunächst über #getFiles(File, boolean) die Kinder ermittelt werden. Danach werden mittels #isTraversable(File) die traversierbaren Kinder herausgefiltert. Anschließend werden sie sortiert und zu jedem Verzeichniskind ein DirectoryTreeNode als Baumkind verfügbar gemacht (siehe Listing 1). ChooseDirectoryDialog ist eine JDialog-Unterklasse, die einen JTree zu einem TreeModel von DirectoryTreeNodes verwendet. Der Dialog verwendet die FileSystemView-Methoden #getRoots() um die Wurzel(n) der Dateisystempräsentation zu ermitteln und #getSystemDisplayName(File) sowie #getSystemIcon(File) zum Rendern der Zellen im Verzeichnisbaum. Zusätzlich könnte ein Test der aktuellen Auswahl auf #isFileSystem(File) dazu dienen, nur Ordner mit einer Entsprechung im Dateisystem wählen zu können (siehe Listing 2). Der volle Quelltext zu diesen Klassen ist auf der beiliegenden CD enthalten. Über die Testklasse ChooseDirectoryTest lässt sich ein Verzeichnis auswählen, zu dem anschließend in die Konsole ein paar der oben erläuterten FileSystemView-Eigenschaften ausgegeben werden.

Listing 1

Geschrieben von
Karsten Lentzsch
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.