All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.rap.rwt.RWT Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2007, 2019 Innoopract Informationssysteme GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Innoopract Informationssysteme GmbH - initial API and implementation
 *    EclipseSource - ongoing implementation
 *    Ralf Zahn (ARS) - browser history support (Bug 283291)
 *    Frank Appel - replaced singletons and static fields (Bug 337787)
 ******************************************************************************/
package org.eclipse.rap.rwt;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.eclipse.rap.rwt.application.Application;
import org.eclipse.rap.rwt.client.Client;
import org.eclipse.rap.rwt.internal.lifecycle.CurrentPhase;
import org.eclipse.rap.rwt.internal.lifecycle.LifeCycle;
import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleUtil;
import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.rap.rwt.internal.service.ServletLog;
import org.eclipse.rap.rwt.internal.util.ClassUtil;
import org.eclipse.rap.rwt.internal.util.ParamCheck;
import org.eclipse.rap.rwt.service.ApplicationContext;
import org.eclipse.rap.rwt.service.ResourceManager;
import org.eclipse.rap.rwt.service.ServiceManager;
import org.eclipse.rap.rwt.service.SettingStore;
import org.eclipse.rap.rwt.service.UISession;
import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.widgets.IDisplayAdapter;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


/**
 * This class provides access to those parts of RWT which are not covered by the SWT API. For
 * example, it provides access to the current UI session and the request.
 *
 * @since 2.0
 * @see UISession
 * @see ApplicationContext
 * @see ResourceManager
 * @see HttpServletRequest
 * @see HttpServletResponse
 */
public final class RWT {

  /**
   * 

This utility class helps to provide a similar approach for compile safe * native language support than {@link org.eclipse.osgi.util.NLS NLS} does. * We can not use the original approach though, due to the nature of * server side environments, that have to deal with different locales * per user session or even requests.

* *

* Usage: *

   *  public class FooMessages {
   *    private static final String BUNDLE_NAME = "foo.bar.messages";
   *
   *    public String MyMessage;
   *
   *    public static FooMessages get() {
   *      return ( FootMessages )RWT.NLS.getISO8859_1Encoded( BUNDLE_NAME, FooMessages.class );
   *    }
   *  }
   * 
* * BUNDLE_NAME contains the name of a properties file (without file extension) * that follows the conventions of standard {@link ResourceBundle} property * files. For each field (in the example 'MyMessage') there has to be a * key entry in the localization property file. Use the * FooMessages like this in the application code: * *
   *   Label label = ...;
   *   label.setText( FooMessages.get().MyMessage );
   * 
*

*/ @SuppressWarnings("javadoc") public static final class NLS { private final static Map map = new HashMap<>(); /** * Returns a NLS object for the given resource bundle and type. See * class description for usage information. * The resource bundles read by this method have to be ISO 8859-1 encoded. * This is according to the {@link java.util.Properties Properties} file * specification. * * @param bundleName the resource bundle to load. * @param clazz the class of the NLS object to load. * * @deprecated use get(String bundleName, Class clazz) instead. */ @Deprecated public static T getISO8859_1Encoded( String bundleName, Class clazz ) { return get( bundleName, clazz ); } /** * Returns a NLS object for the given resource bundle and type. See * class description for usage information. * The resource bundles read by this method have to be UTF-8 encoded. Note * that this is not according to the {@link java.util.Properties Properties} * file specification and meant for a more convenient use. * * @param bundleName the resource bundle to load. * @param clazz the class of the NLS object to load. * * @deprecated use get(String bundleName, Class clazz) instead. */ @Deprecated public static T getUTF8Encoded( String bundleName, Class clazz ) { return get( bundleName, clazz ); } /** * Returns a NLS object for the given resource bundle and type. See * class description for usage information. * * @param bundleName the resource bundle to load. * @param clazz the class of the NLS object to load. * * @since 3.23 */ @SuppressWarnings( "unchecked" ) public static T get( String bundleName, Class clazz ) { T result; ClassLoader loader = clazz.getClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle( bundleName, getLocale(), loader ); synchronized( map ) { result = ( T )map.get( bundle ); if( result == null ) { result = ClassUtil.newInstance( clazz ); Field[] fields = clazz.getDeclaredFields(); for( int i = 0; i < fields.length; i++ ) { String fieldName = fields[ i ].getName(); try { if( String.class.isAssignableFrom( fields[ i ].getType() ) && Modifier.isPublic( fields[ i ].getModifiers() ) && !Modifier.isStatic( fields[ i ].getModifiers() ) ) { try { String value = bundle.getString( fieldName ); if( value != null ) { fields[ i ].setAccessible( true ); fields[ i ].set( result, value ); } } catch( MissingResourceException mre ) { fields[ i ].setAccessible( true ); fields[ i ].set( result, "" ); throw mre; } } } catch( Exception ex ) { String qualifiedName = clazz.getName() + "#" + fieldName; ServletLog.log( "Failed to load localized message for: " + qualifiedName, ex ); } } map.put( bundle, result ); } } return result; } } /** * The property to use in Display.setData() in order to activate global key events * for certain key sequences. The value for this property has to be an array of Strings, each * representing a key sequence. When this property is set on the display, the client will be * instructed to issue events for the given key sequences. These key events can be captured using * Display.addFilter(). *

* The property can also be used in Control.setData(). In this case, a key listener * that is attached to that control will only receive events for the specified key sequences. * Control without active keys set will issue events for all key strokes. *

*

* Valid strings for key sequences consist of one key and any number of modifier keys, * separated by +. Keys can be identified by their upper case character or by any * of the keywords below. Special characters (not a letter or digit) should not be combined with * any modifiers, and will issue events regardless of pressed modifiers. *

*

* The following keywords can be used to refer to special keys: * BACKSPACE, TAB, RETURN, * ENTER, ESCAPE, SPACE, PAGE_UP, * PAGE_DOWN, END, HOME, ARROW_LEFT, * ARROW_UP, ARROW_RIGHT, ARROW_DOWN, INSERT, * DELETE, F1, F2, F3, F4, * F5, F6, F7, F8, F9, * F10, F11, F12, Valid modifier keys are * SHIFT, ALT, and CTRL. *

* Examples: "A", "#", "F12", * "CTRL+1", "ALT+ARROW_DOWN", * "ALT+SHIFT+X". *

*

*

* Example code for implementing a key binding:

   * display.setData( RWT.ACTIVE_KEYS, new String[] { "CTRL+1", "CTRL+2" } );
   * display.addFilter( SWT.KeyDown, new Listener() {
   *   public void handleEvent( Event event ) {
   *     boolean ctrlPressed = ( event.stateMask & SWT.Ctrl ) != 0;
   *     if( ctrlPressed && event.character == '1' ) {
   *       // handle Ctrl+1
   *     }
   *   }
   * } );
   * 
*

* * @see Display#setData(String,Object) * @see Display#addFilter(int, Listener) * @see RWT#CANCEL_KEYS */ public static final String ACTIVE_KEYS = "org.eclipse.rap.rwt.activeKeys"; /** * The property to use in Display.setData() in order to always cancel the client's * default operation associated with certain key sequences. It allows the same values as * {@link RWT#ACTIVE_KEYS}. If a key sequences is given in {@link RWT#CANCEL_KEYS} as well as * in {@link RWT#ACTIVE_KEYS}, it will cancel its default operation, but still issue the event. *

* The property can also be used in Control.setData(). In this case, the associated * default operation will only be cancelled if the control is focused. *

* *

* Depending on the client, there may be certain keys that cannot be cancelled. *

* * @see Display#setData(String,Object) * @see RWT#ACTIVE_KEYS */ public static final String CANCEL_KEYS = "org.eclipse.rap.rwt.cancelKeys"; /** * The property to use in Display.setData() in order to set the key combination for * mnemonics activation. The value for this property has to be a String. *

* Valid string for key sequence consist of any number of modifier keys, separated by * +. *

*

* Mnemonics are currently supported by MenuItem, Button, * Label, CLabel, Group, ToolItem, * TabItem and CTabItem. Mnemonics are not supported on a widgets * with enabled markup. *

*

* Example code:

   * display.setData( RWT.MNEMONIC_ACTIVATOR, "ALT+CTRL" );
   * 
*

* * @see Display#setData(String,Object) * @since 2.1 */ public static final String MNEMONIC_ACTIVATOR = "org.eclipse.rap.rwt.mnemonicActivator"; /** * The property to use in Control.setData() in order to set a custom item height. * The custom item height must be specified as an Integer and passed to * setData() with this constant as the key. *

* For example: * table.setData( RWT.CUSTOM_ITEM_HEIGHT, Integer.valueOf( 45 ) ); *

*

Used By:

    *
  • Table
  • *
  • Tree
  • *
  • List
  • *

* * @see Control#setData(String,Object) */ public static final String CUSTOM_ITEM_HEIGHT = "org.eclipse.rap.rwt.customItemHeight"; /** * Controls the number of preloaded items outside (above and below) visible area of virtual * Tree or Table. The preloaded items must be specified as an * Integer and passed to setData() with this constant as the key. *

* For example: table.setData( RWT.PRELOADED_ITEMS, Integer.valueOf( 10 ) ); *

*

* Used By: *

    *
  • Table
  • *
  • Tree
  • *
*

* * @see Control#setData(String,Object) * @since 2.2 */ public static final String PRELOADED_ITEMS = "org.eclipse.rap.rwt.preloadedItems"; /** * Controls whether the use of markup in text is enabled. To enable * markup in text, this constant must be passed to setData() with * a value of Boolean.TRUE. The call to setData() * must be placed directly after the control is created. Once the markup in text * is enabled it's not possible to disable it. *

* For example: *

   *   Table table = new Table( parent, SWT.NONE );
   *   table.setData( RWT.MARKUP_ENABLED, Boolean.TRUE );
   * 
*

*

* When markup is enabled, certain XHTML tags can be used in the text property * of the respective widget. Specifying an unsupported element will lead to an * {@link IllegalArgumentException} when setting the text. The following table * lists the currently supported tags: *

*
{@literal text}
*
renders its content in bold font style
*
{@literal text}
*
renders its content in italic font style
*
{@literal
}
*
inserts a line break
*
{@literal }
*
renders its content as subscript
*
{@literal }
*
renders its content as superscript
*
{@literal }
*
renders its content with bigger font size
*
{@literal }
*
renders its content with smaller font size
*
{@literal }
*
renders its content as deleted text
*
{@literal }
*
renders its content as inserted text
*
{@literal }
*
renders its content as emphasized text
*
{@literal }
*
renders its content as strong emphasized text
*
{@literal }
*
renders its content as instance definition
*
{@literal }
*
renders its content as computer code fragment
*
{@literal }
*
renders its content as sample program output
*
{@literal }
*
renders its content as text to be entered by the user
*
{@literal }
*
renders its content as instance of a variable or program argument
*
{@literal }
*
renders its content as citation
*
{@literal }
*
renders its content as short inline quotation
*
{@literal }
*
renders its content as abbreviation
*
{@literal }
*
generic style container
*
{@literal }
*
renders an image
*
{@literal }
*
renders a hyperlink
*
* The visual representation of the above tags can be specified in a style * attribute. *

*

* Used By: *

    *
  • Table
  • *
  • Tree
  • *
  • Grid
  • *
  • List
  • *
  • Label
  • *
  • CLabel
  • *
  • ToolTip
  • *
  • Button
  • *
*

* * @see Control#setData(String,Object) * @see RWT#HYPERLINK */ public static final String MARKUP_ENABLED = "org.eclipse.rap.rwt.markupEnabled"; /** * Controls whether the use of markup in tooltip text is enabled. To enable * markup in tooltip text, this constant must be passed to setData() with * a value of Boolean.TRUE. The call to setData() * must be placed directly after the control is created. Once, the markup in tooltip text * is enabled it's not possible to disable it. * * @see Control#setData(String,Object) * @see RWT#MARKUP_ENABLED * @since 2.2 */ public static final String TOOLTIP_MARKUP_ENABLED = "org.eclipse.rap.rwt.tooltipMarkupEnabled"; /** * Controls the number of fixed columns. This constant must be passed to setData() * together with an Integer object. The given number of columns, starting * with the current leftmost one, will not scroll horizontally. The call to setData() * must be placed directly after the control is created. *

* For example: *

   *   Table table = new Table( parent, SWT.NONE );
   *   table.setData( RWT.FIXED_COLUMNS, Integer.valueOf( 2 ) );
   * 
*

* Used By: *
    *
  • Table
  • *
  • Tree
  • *
*

* * @see Control#setData(String,Object) */ public static final String FIXED_COLUMNS = "org.eclipse.rap.rwt.fixedColumns"; /** * Controls the text shown as a badge. This constant must be passed to setData() * together with an String object. *

* For example: *

   *   TabItem item = new TabItem( folder, SWT.NONE );
   *   item.setData( RWT.BADGE, "23" );
   * 
*

* Used By: *
    *
  • TabItem
  • *
*

* * @see Control#setData(String,Object) * @since 3.0 */ public static final String BADGE = "org.eclipse.rap.rwt.badge"; /** * The ID of the default theme. The default theme is the active theme if no * custom theme has been specified. This ID can be used to register theme * contributions to the default theme. * * @see Application#addStyleSheet(String, String) */ public static final String DEFAULT_THEME_ID = "org.eclipse.rap.rwt.theme.Default"; /** * Used to mark a widget as belonging to a custom variant in order to apply a * different theming to it. A custom variant can be applied to any widget like this: * *
   * button.setData( RWT.CUSTOM_VARIANT, "mybutton" );
   * 
* * For more information on custom variants, see the RAP help on theming. * * @see Widget#setData(String,Object) * @since 2.0 */ public static final String CUSTOM_VARIANT = "org.eclipse.rap.rwt.customVariant"; /** * Used to apply a row template to a control. Row templates replace the column layout model of a * Tree or a Table with a custom presentation defined by an instance of * {@link org.eclipse.rap.rwt.template.Template}. A template cell will display the content of an * item's column when its bindingIndex is set to the corresponding column index. *

* To apply a row template on a control, use the control's setData() method with this * constant as key: *

* *
   * Template template = new Template();
   * // add cells to this template
   * new TextCell(template).setBindingIndex(0).setTop(10).setLeft(20) ...;
   * ...
   * Table table = new Table(parent, SWT.FULL_SELECTION);
   * // Add as many columns as needed to add multiple texts/images to items
   * new TableColumn();
   * ...
   * table.setData(RWT.ROW_TEMPLATE, template);
   * 
*

* The call to setData() must be placed directly after the control's creation. Once a * template is applied to a control, the control will not be affected by changes to the template. *

*

* Note that TableColumn/TreeColumn instances must be created in order to support multiple item * texts/images. If the SWT.FULL_SELECTION style flag is not set, no selection will * be displayed. *

*

* Supported by: *

    *
  • Table
  • *
  • Tree
  • *
  • Grid
  • *
*

* * @see org.eclipse.swt.widgets.Control#setData(String,Object) * @see org.eclipse.rap.rwt.template.Template * @since 2.2 */ public static final String ROW_TEMPLATE = "org.eclipse.rap.rwt.rowTemplate"; /** * Used as detail information on a selection event to indicate that a hyperlink (anchor * tag) in a markup text was selected instead of the widget that contains the markup. To enable * selection events on markup hyperlinks, the a element must have it's * target property set to “_rwt”. * *

* Supported by: *

    *
  • Table
  • *
  • Tree
  • *
  • Grid
  • *
  • List
  • *
*

* * @see RWT#MARKUP_ENABLED * @see org.eclipse.swt.events.SelectionEvent#detail * @since 2.1 */ public static final int HYPERLINK = 1 << 26; /** * Used as as detail information on a selection event to indicate that a selectable * template cell was selected instead of the widget that contains the cell. * * @see org.eclipse.rap.rwt.template.Cell#setSelectable(boolean) * @see org.eclipse.swt.events.SelectionEvent#detail * @since 2.2 */ public static final int CELL = 1 << 27; /** * Returns the instance of the resource manager for the current application context. This is a * shortcut for RWT.getApplicationContext().getResourceManager(). * * @return the resource manager for the current application context * @see ApplicationContext#getResourceManager() */ public static ResourceManager getResourceManager() { return getApplicationContext().getResourceManager(); } /** * Returns the instance of the service manager for the current application context. This is a * shortcut for RWT.getApplicationContext().getServiceManager(). * * @return the service manager instance for the current application context * @see ApplicationContext#getServiceManager() */ public static ServiceManager getServiceManager() { return getApplicationContext().getServiceManager(); } /** * Returns the setting store instance for the current UI session. The setting store is a * persistent store for user-specific data. * * @return the setting store for the current session, never null */ public static SettingStore getSettingStore() { return ContextProvider.getApplicationContext().getSettingStoreManager().getStore(); } /** * Returns the current UI session. This method must be executed from the UI thread. * * @return the current UI session instance, never null * @throws IllegalStateException when called outside of the UI thread */ public static UISession getUISession() { checkContext(); return ContextProvider.getUISession(); } /** * Returns the UI session that is associated with the given display. * * @return the UI session instance for the given display, never null */ public static UISession getUISession( Display display ) { ParamCheck.notNull( display, "display" ); return display.getAdapter( IDisplayAdapter.class ).getUISession(); } /** * Returns the ApplicationContext instance that represents the web context's * global data storage area. * * @return instance of {@link ApplicationContext} */ public static ApplicationContext getApplicationContext() { checkContext(); return ContextProvider.getApplicationContext(); } /** * Returns the HttpServletRequest that is currently processed. *

* Note: This method is not recommended. Typical application * code should not need to call this method. Processing requests from the client is up to the * framework. In rare cases, an application may be wish to access request details such as certain * HTTP headers. *

* * @return the currently processed request * @since 4.0 */ public static HttpServletRequest getRequest() { checkContext(); return ContextProvider.getRequest(); } /** * Returns the HttpServletResponse that will be sent to the client after processing * the current request. *

* Note: This method is not recommended. Typical application * code should not need to call this method. The response should only be written and modified by * the framework. In rare cases, an application may wish to access the response, e.g. to add a * Cookie. *

* * @return the response object that will be sent to the client * @since 4.0 */ public static HttpServletResponse getResponse() { checkContext(); return ContextProvider.getResponse(); } /** * Returns the preferred Locale for the current UI session. * This method is a shortcut for RWT.getUISession().getLocale(). * * @return the preferred Locale for the current UI session. * * @see UISession#getLocale() */ public static Locale getLocale() { return getUISession().getLocale(); } /** * Sets the preferred Locale for the current UI session. This method is a shortcut * for RWT.getUISession().setLocale( locale ). * * @param locale the locale to set, or null to reset * @see UISession#setLocale(Locale) */ public static void setLocale( Locale locale ) { getUISession().setLocale( locale ); } /** * Executes the run method of the given runnable on the * request thread. This method may only be called from the UI thread. *

* NOTE: This API is provisional and may change without * further notice. *

* @param runnable the code to be executed on the request thread * @throws IllegalStateException when called from a non-UI thread */ public static void requestThreadExec( Runnable runnable ) { ParamCheck.notNull( runnable, "runnable" ); checkContext(); checkPhase(); Display display = LifeCycleUtil.getSessionDisplay(); if( display == null || display.isDisposed() ) { SWT.error( SWT.ERROR_DEVICE_DISPOSED ); } LifeCycle lifeCycle = ContextProvider.getApplicationContext().getLifeCycleFactory().getLifeCycle(); lifeCycle.requestThreadExec( runnable ); } /** * Returns a representation of the client that is connected with the server in the current UI * session. This is a shortcut for RWT.getUISession().getClient(). * * @return The client for the current UI session * @throws IllegalStateException when called outside of the request context */ public static Client getClient() { return getUISession().getClient(); } private static void checkContext() { if( !ContextProvider.hasContext() ) { throw new IllegalStateException( "Invalid thread access" ); } } private static void checkPhase() { if( CurrentPhase.get() == null ) { throw new IllegalStateException( "Invalid thread access" ); } } private RWT() { // prevent instantiation } }