Add WidgetDataWhiteList class 

This class provides a public interface for adding keys to the internal
WidgetDataWhiteList service.
diff --git a/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
index a586cc1..7d15f20 100644
--- a/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
@@ -20,3 +20,4 @@
  org.eclipse.swt,
  org.eclipse.swt.events,
  org.eclipse.swt.widgets
+Require-Bundle: org.eclipse.rap.rwt
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList.java
new file mode 100644
index 0000000..5736348
--- /dev/null
+++ b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2013 EclipseSource 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:
+ *    EclipseSource - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.clientscripting;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.client.Client;
+import org.eclipse.rap.rwt.internal.client.WidgetDataWhiteListImpl;
+
+@SuppressWarnings("restriction")
+public class WidgetDataWhiteList {
+
+  /**
+   * Adds a string to the list of keys of widget data that are synchronized with the client.
+   * It is save to add the same key twice, there are no side-effects. The data is only transferred from
+   * server to client, not back. Widgets can currently not be transferred directly, use their
+   * id instead, i.e.
+   * <p><code>
+   *   widget.setData( "otherWidget", WidgetUtil.getId( otherWidget ) );
+   * </code></p>
+   * and in JavaScript:
+   * <p><code>
+   *   var otherWidget = rap.getObject( widget.getData( "otherWidget" ) );
+   * </code></p>
+   * @see org.eclipse.swt.widgets.Widget#setData(String, Object)
+   * @param string The key to add to the list.
+   */
+  public static void addKey( String string ) {
+    WidgetDataWhiteListImpl service = getWhiteListService();
+    List<String> list = getCurrentKeys( service );
+    if( !list.contains( string ) ) {
+      list.add( string );
+      service.setKeys( list.toArray( new String[ list.size() ]) );
+    }
+  }
+
+  private static List<String> getCurrentKeys( WidgetDataWhiteListImpl service ) {
+    String[] currentKeys = service.getKeys() != null ? service.getKeys() : new String[ 0 ];
+    return new ArrayList<String>( Arrays.asList( currentKeys ) );
+  }
+
+  private static WidgetDataWhiteListImpl getWhiteListService() {
+    Client client = RWT.getClient();
+    org.eclipse.rap.rwt.internal.client.WidgetDataWhiteList service
+      = client.getService( org.eclipse.rap.rwt.internal.client.WidgetDataWhiteList.class );
+    return ( WidgetDataWhiteListImpl )service;
+  }
+}
diff --git a/tests/org.eclipse.rap.clientscripting.test/META-INF/MANIFEST.MF b/tests/org.eclipse.rap.clientscripting.test/META-INF/MANIFEST.MF
index be0917d..7561a4b 100644
--- a/tests/org.eclipse.rap.clientscripting.test/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.rap.clientscripting.test/META-INF/MANIFEST.MF
@@ -10,4 +10,5 @@
  org.mockito;bundle-version="[1.8.4,2.0.0)",
  org.objenesis;bundle-version="[1.0.0,2.0.0)"
 Import-Package: javax.servlet;version="2.6.0",
+ org.eclipse.rap.rwt.internal.client;version="2.0.0",
  org.eclipse.rap.rwt.testfixture;version="[2.0.0,3.0.0)"
diff --git a/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList_Test.java b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList_Test.java
new file mode 100644
index 0000000..3a3a5b9
--- /dev/null
+++ b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/WidgetDataWhiteList_Test.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2013 EclipseSource 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:
+ *    EclipseSource - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.clientscripting;
+
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.stub;
+import static org.mockito.Mockito.verify;
+
+import org.eclipse.rap.rwt.client.Client;
+import org.eclipse.rap.rwt.internal.client.WidgetDataWhiteListImpl;
+import org.eclipse.rap.rwt.testfixture.Fixture;
+import org.junit.Before;
+import org.junit.Test;
+
+@SuppressWarnings( "restriction" )
+public class WidgetDataWhiteList_Test {
+
+  private WidgetDataWhiteListImpl whiteList;
+
+  @Before
+  public void setUp() throws Exception {
+    Fixture.setUp();
+    Fixture.fakeNewRequest();
+    Client client = mock( Client.class );
+    whiteList = mock( WidgetDataWhiteListImpl.class );
+    Class<org.eclipse.rap.rwt.internal.client.WidgetDataWhiteList> type
+      = org.eclipse.rap.rwt.internal.client.WidgetDataWhiteList.class;
+    stub( client.getService( eq( type ) ) ).toReturn( whiteList );
+    Fixture.fakeClient( client );
+  }
+
+  @Test
+  public void testAddKey_Once() {
+    WidgetDataWhiteList.addKey( "foo" );
+
+    verify( whiteList ).setKeys( eq( new String[] { "foo" } ) );
+  }
+
+  @Test
+  public void testAddKey_DoNothingIfAlreadyInList() {
+    stub( whiteList.getKeys() ).toReturn( new String[] { "foo" } );
+
+    WidgetDataWhiteList.addKey( "foo" );
+
+    verify( whiteList, never() ).setKeys( any( String[].class ) );
+  }
+
+  @Test
+  public void testAddKey_DoNotOverwriteExistingKeys() {
+    stub( whiteList.getKeys() ).toReturn( new String[] { "bar" } );
+
+    WidgetDataWhiteList.addKey( "foo" );
+
+    verify( whiteList ).setKeys( eq( new String[]{ "bar", "foo" } ) );
+  }
+
+}