Wie lassen sich fremde Systembibliotheken in eine Cross-Plattform-Applikation einbinden?

Wenn man eine Java-Applikation plattformübergreifend schreiben möchte, jedoch nicht auf systemeigene Bibliotheken verzichten will, greift man auf das Strategy-Pattern zurück. Hier soll am Beispiel eines Ausschnitts des Quelltextes von Cent das Vorgehen erläutert werden.
Das hier gezeigt Verfahren gilt mittlerweile teilweise als 'deprecated' und sollte durch dasjenige ersetzt werden, das im Artikel MacOSX Menuleiste gezeigt wird.

Betrachten wir als Beispiel Apples MacOS X. Das Betriebssystem stellt eine eigene Bibliothek bereit, um Java-Programme vollständig in das System integrieren zu können. Hierzu zählt z.B. der Aufruf des obligatorischen Eigenschaften- oder Hilfe-Dialogs aus der oberen Desktop-Leiste heraus. Diese Bibliothek ist auf anderen Betriebssystemen natürlich nicht vorhanden, sodass Cross-Plattform-Entwicklungen auf die Einbindung verzichten müssten. Das würde zwar die Funktionalität nicht beeinträchtigen, ließe jedoch die Homogenität der Gesamt-Erscheinung vermissen. Um in deren Genuss zu kommen, muss die Bibliothek beim Kompilieren natürlich im Klassenpfad vorhanden sein.
Wie stellt man es nun an, diese Bibliothek auf Quelltextebene einzubinden ohne zur Laufzeit auf anderen Systemen eine Fehlermeldung zu erhalten?
Das prizipielle Vorgehen wird im Abschnitt Strategy-Pattern erläutert. Dem entsprechend wird eine Klasse MacImpl deklariert, die einerseits Apples Pakete


com.apple.eawt.Application;
com.apple.eawt.ApplicationEvent;
com.apple.eawt.ApplicationListener;

einbindet, andererseits ein kleines Interface ClassSelector implementiert. Es deklariert nur eine Methode handleOS(). Sie kann je nach Betriebssystem in unterschiedlichen Klassen konkretisiert werden.
Die Methode handleOS() erzeugt im vorliegenden Fall ein Application-Objekt, auf dem der Reihe nach Methoden aufgerufen werden, um

Die dann folgenden Methoden entstammen dem implementierten Interface ApplicationListener. Ihre Bezeichner sind selbsterklärend und können mit beliebigen Routinen realisiert werden.
Der "Witz" besteht jetzt darin, dass in main() durch die Zeile

System.getProperties().put("apple.laf.useScreenMenuBar", "true");

zunächst die Nutzung der Menuleiste angefordert wird. Das muss bereits an dieser Stelle erfolgen, um die vollständige Darstellung der Apple-Leiste zu gewährleisten. Da es sich hierbei lediglich um den Eintrag einer Systemeigenschaft handelt, wird auf anderen Betriebssystemen hierdurch kein Fehler erzeugt. In der Folge wird das Betriebssystem abgefragt und erst dann wird, je nach Ergebnis, die entsprechende Klasse aufgerufen. Das garantiert, dass nicht vorhandene Bibliotheken zur Laufzeit auch nicht benötigt werden.



import java.util.Properties;

import javax.swing.ImageIcon;

import com.apple.eawt.Application;
import com.apple.eawt.ApplicationEvent;
import com.apple.eawt.ApplicationListener;

import de.yourwebs.cent.CentGUI;
import de.yourwebs.cent.CentSplash;
import de.yourwebs.cent.Config;
import de.yourwebs.cent.dialogs.AboutDialog;
import de.yourwebs.cent.dialogs.options.OptionsDialog;

public class Cent {

    public static void main(String[] args) {

        System.getProperties().put("apple.laf.useScreenMenuBar", "true");
        
        Cent cent = new Cent();
        
        CentGUI.getCentGUI();

        if (Config.getOS().equals("mac")) {
            new MacImpl();
        }
    }
}

class MacImpl implements ClassSelector, ApplicationListener {
    
    public MacImpl(){
        handleOS();
    }

    @Override
    public void handleOS() {
        try {
            final Application application = Application.getApplication();
            application.setDockIconImage(new ImageIcon(ClassLoader.getSystemResource(Config.IMG_VERZ
                    + Config.APP_NAME.toLowerCase() + "512.png")).getImage());
            application.setEnabledAboutMenu(true);
            application.addPreferencesMenuItem();
            application.setEnabledPreferencesMenu(true);
            application.addApplicationListener(this);
        } catch (Throwable e) {
            System.err.println("setupMacOSXApplicationListener failed: "
                    + e.getMessage());
        }
    }
    
    public void handleAbout(ApplicationEvent arg0) {
        new AboutDialog(CentGUI.getCentGUI());
        arg0.setHandled(true);
    }

    public void handleOpenApplication(ApplicationEvent arg0) {
    }

    public void handleOpenFile(ApplicationEvent arg0) {
    }

    public void handlePreferences(ApplicationEvent arg0) {
        new OptionsDialog();
        arg0.setHandled(true);
    }

    public void handlePrintFile(ApplicationEvent arg0) {
    }

    public void handleQuit(ApplicationEvent arg0) {
        arg0.setHandled(true);
        System.exit(0);
    }

    public void handleReOpenApplication(ApplicationEvent arg0) {
    }
}

interface ClassSelector {
    public void handleOS();
}

Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.