Es folgt eine Beschreibung der relevanten Schnittstellen sowie konkrete Beispiele:
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!!!
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 }
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
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 }
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:
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
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.