6.3.1. Der Toolkit Interceptor

Es folgt eine Beschreibung der relevanten Schnittstellen sowie konkrete Beispiele:

Die Schnittstelle IToolkitInterceptor

Die Schnittstelle IToolkitInterceptor hat die folgende Methode:

    void onToolkitCreate(IToolkit toolkit);

Diese Methode wird aufgerufen, nachdem das Toolkit erzeugt wurde, jedoch bevor die Toolkit Instanz über die Klasse Toolkit verfügbar ist. Aus diesem Grund wird die neu erzeugte Instanz als Parameter übergeben. Dadurch ist sicher gestellt, dass alle Toolkit Interceptoren vor der ersten Benutzung des Toolkit ausgeführt werden. Wenn onToolkitCreate() aufgerufen wird, hat jowidgets bereits seine Core Widgets, Icons und Defaults registriert.

Achtung:

Der Aufruf von Toolkit.getInstance() sowie allen anderen indirekten Aufrufen davon, wie zum Beispiel Toolkit.getBluePrintProxyFactory() führen zu einem Fehler. Stattdessen muss man zum Beispiel toolkit.getBluePrintProxyFactory() schreiben. Zudem sollten in einem Toolkit Interceptor keine Widgets erzeugt werden!!!

Toolkit Interceptor Beispiel

Das folgende Beispiel zeigt eine gekürzte Version des Toolkit Interceptor für die jo-client-platform. Der vollständige Code findet sich hier.

  1  final class CapToolkitInterceptor implements IToolkitInterceptor {
  2  
  3      @Override
  4      public void onToolkitCreate(final IToolkit toolkit) {
  5          registerWidgets(toolkit);
  6          registerIcons(toolkit);
  7          addDefaultsInitializer(toolkit);
  8          setBuilderConvenience(toolkit);
  9          registerConverter(toolkit);
 10      }
 11  
 12      @SuppressWarnings("unchecked")
 13      private void registerWidgets(final IToolkit toolkit) {
 14          final IGenericWidgetFactory factory = toolkit.getWidgetFactory();
 15          
 16          factory.register(
 17              IBeanTableBluePrint.class, 
 18              new BeanTableFactory());
 19          
 20          //... removed some widgets in this example
 21          
 22          factory.register(
 23              IBeanLinkDialogBluePrint.class,
 24              new BeanLinkDialogFactory());
 25      }
 26  
 27      private void registerIcons(final IToolkit toolkit) {
 28          final IImageRegistry registry = toolkit.getImageRegistry();
 29      
 30          registry.registerImageConstant(
 31              CapIcons.TABLE_HIDE_COLUMN, 
 32              IconsSmall.SUB);
 33          
 34          //... removed some icons in this example
 35  
 36          registerImage(registry, CapIcons.NODE_CONTRACTED, "node_contracted.png");
 37      }
 38  
 39      private void registerImage(
 40          final IImageRegistry registry, 
 41          final IImageConstant imageConstant, 
 42          final String relPath) {
 43          
 44          String path = "org/jowidgets/cap/ui/icons/" + relPath;
 45          final URL url = getClass().getClassLoader().getResource(path);
 46          
 47          registry.registerImageConstant(imageConstant, url);
 48      }
 49  
 50      private void registerConverter(final IToolkit toolkit) {
 51          final IConverterProvider converterProvider = toolkit.getConverterProvider();
 52          converterProvider.register(IDocument.class, new DocumentConverter());
 53      }
 54  
 55      private void addDefaultsInitializer(final IToolkit toolkit) {
 56          final IBluePrintProxyFactory bppf = toolkit.getBluePrintProxyFactory();
 57          
 58          bppf.addDefaultsInitializer(
 59              IBeanTableSetupBuilder.class, 
 60              new BeanTableDefaults());
 61              
 62          //... removed some defaults in this example
 63              
 64          bppf.addDefaultsInitializer(
 65              ILookUpComboBoxSelectionBluePrint.class, 
 66              new LookUpComboBoxSelectionDefaults());
 67      }
 68  
 69      private void setBuilderConvenience(final IToolkit toolkit) {
 70          final IBluePrintProxyFactory bppf = toolkit.getBluePrintProxyFactory();
 71          
 72          bppf.setSetupBuilderConvenience(
 73              IBeanTableSetupBuilder.class, 
 74              new BeanTableSetupConvenience());
 75          
 76          //... removed some convenience methods in this example
 77          
 78          bppf.setSetupBuilderConvenience(
 79              IBeanRelationTreeDetailSetupBuilder.class, 
 80              new BeanRelationTreeDetailSetupConvenience());
 81      }
 82  
 83  }
Die Schnittstelle IToolkitInterceptorHolder

Um einen Toolkit Interceptor zu registrieren, benötigt man einen IToolkitInterceptorHolder. Die Schnittstelle sieht wie folgt aus:

  1  public interface IToolkitInterceptorHolder {
  2  
  3      int DEFAULT_ORDER = 2;
  4  
  5      int getOrder();
  6      
  7      IToolkitInterceptor getToolkitInterceptor(); 
  8  }

Mit Hilfe der Order kann die Reihenfolge beeinflusst werden, in der Toolkit Interceptoren aufgerufen werden. Ein Interceptor mit einer kleineren Order wird vor einem Interceptor mit einer größeren Order ausgeführt. Die Methode getToolkitInterceptor() wird erst aufgerufen, bevor der Interceptor tatsächlich aufgerufen wird, und nicht bereits bei der Registrierung des Holders.

Die Klasse AbstractToolkitInterceptorHolder

Die Klasse AbstractToolkitInterceptorHolder liefert eine Basisimplementierung der Schnittstelle IToolkitInterceptorHolder. Das folgende Beispiel zeigt die Verwendung anhand des Toolkit Interceptor Holder’s des UI Security Plugin der jo-client-platform. [34]:

  1  public final class CapSecurityUiToolkitInterceptorHolder 
  2      extends AbstractToolkitInterceptorHolder {
  3  
  4      public CapSecurityUiToolkitInterceptorHolder() {
  5          super(Integer.MAX_VALUE);
  6      }
  7  
  8      @Override
  9      protected IToolkitInterceptor createToolkitInterceptor() {
 10          return new CapSecurityUiToolkitInterceptor();
 11      }
 12  
 13  }
Registrierung eines Toolkit Interceptor Holder mittels Java ServiveLoader

Eine Implementierung der Schnittstelle IToolkitInterceptorHolder kann mit Hilfe des Java ServiceLoader Mechanismus registriert werden. Dadurch wird sichergestellt, dass der Interceptor vor der ersten Verwendung des Toolkit aufgerufen wird.

Die folgende Abbildung verdeutlicht dabei das Vorgehen beispielhaft Anhand der Swt Implementierung des Addon Browser Widgets:

Abbildung 47. Toolkit Interceptor Holder mit Service Loader

Toolkit Interceptor Holder mit Service Loader

Im Ordner META-INF/services muss eine Datei mit dem Namen org.jowidgets.api.toolkit.IToolkitInterceptorHolder abgelegt werden, welche den voll qualifizierten Klassennamen aller Implementierungen beinhaltet. Im Beispiel hat die Datei den folgenden Inhalt:

    org.jowidgets.addons.widgets.browser.impl.swt.BrowserToolkitInterceptorHolder
Explizite Registrierung eines Toolkit Interceptor Holder

Die Klasse ToolkitInterceptor liefert die folgende statische Methode zur Registrierung eines IToolkitInterceptorHolder:

    public static void registerToolkitInterceptorHolder(final IToolkitInterceptorHolder holder) {...}

Achtung: Die explizite Registrierung muss immer vor der ersten Verwendung des Toolkit erfolgen, ansonsten hat sie keinen Effekt. Das explizite Registrieren sollte also nur verwendet werden, wenn man diese Bedingung garantieren kann. Man könnte zum Beispiel vermuten, dass in einem RCP Projekt ein IStartup (earlyStartup()) ein guter Zeitpunkt für die Registrierung ist. Allerdings ist unklar, ob der UI Thread erst gestartet wird, nachdem alle earlyStartup() Aufrufe stattgefunden haben (Die API Spezifikation macht dazu jedenfalls keine Aussage.) Falls dies nicht der Fall ist, könnte ein anderes Plugin, welches ebenfalls IStartup verwendet mittels Display.asynExcec() auf das Toolkit zugreifen, bevor der Inteceptor aufgerufen wurde. Aus diesem Grund wird davon dringend abgeraten.



[34] Das UI Plugin liefert keine echten Security Aspekte, denn die liefert das Service Security Plugin. Das Plugin verhindert aber zum Beispiel die Ausführung von Diensten für die keine Rechte vorhanden sind, um die Usability zu erhöhen, oder dekoriert Widgets, so dass zum Beispiel eine BeanTable, falls man keine Leserechte hat, durch ein Composite mit Informationen darüber an den Nutzer, ersetzt wird.


Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation