Use new JavaScriptLoader to load resources

Concatenate all JavaScript resources and register only a single file.
Remove IResource extensions.
diff --git a/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
index 2f54137..11fbc5e 100644
--- a/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.rap.clientscripting/META-INF/MANIFEST.MF
@@ -10,6 +10,8 @@
 Bundle-Vendor: Eclipse.org - RAP Incubator
 Import-Package: org.eclipse.rap.rwt;version="[2.0.0,3.0.0)",
  org.eclipse.rap.rwt.application;version="[2.0.0,3.0.0)",
+ org.eclipse.rap.rwt.client;version="[2.0.0,3.0.0)",
+ org.eclipse.rap.rwt.client.service;version="[2.0.0,3.0.0)",
  org.eclipse.rap.rwt.internal.protocol;version="[2.0.0,3.0.0)",
  org.eclipse.rap.rwt.lifecycle;version="[2.0.0,3.0.0)",
  org.eclipse.rap.rwt.resources;version="[2.0.0,3.0.0)",
@@ -17,4 +19,3 @@
  org.eclipse.swt,
  org.eclipse.swt.events,
  org.eclipse.swt.widgets
-Require-Bundle: org.eclipse.rap.ui;bundle-version="2.0.0";resolution:=optional
diff --git a/bundles/org.eclipse.rap.clientscripting/build.properties b/bundles/org.eclipse.rap.clientscripting/build.properties
index 03e7f26..918e8d8 100644
--- a/bundles/org.eclipse.rap.clientscripting/build.properties
+++ b/bundles/org.eclipse.rap.clientscripting/build.properties
@@ -2,5 +2,4 @@
            js/
 output.. = bin/
 bin.includes = META-INF/,\
-               .,\
-               plugin.xml
+               .
diff --git a/bundles/org.eclipse.rap.clientscripting/plugin.xml b/bundles/org.eclipse.rap.clientscripting/plugin.xml
deleted file mode 100644
index 034e096..0000000
--- a/bundles/org.eclipse.rap.clientscripting/plugin.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.4"?>
-<plugin>
-   <extension
-         point="org.eclipse.rap.ui.resources">
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.ClientScriptingUtilResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.EventBindingResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.EventBindingAdapterResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.EventProxyResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.FunctionResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.ListenerAdapterResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.SWTResource">
-      </resource>
-      <resource
-            class="org.eclipse.rap.clientscripting.internal.resources.WidgetProxyResource">
-      </resource>
-   </extension>
-
-</plugin>
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/ClientListener.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/ClientListener.java
index 0391f91..657b8d3 100644
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/ClientListener.java
+++ b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/ClientListener.java
@@ -17,8 +17,9 @@
 import org.eclipse.rap.clientscripting.internal.ClientListenerAdapter;
 import org.eclipse.rap.clientscripting.internal.ClientListenerBinding;
 import org.eclipse.rap.clientscripting.internal.ClientListenerManager;
-import org.eclipse.rap.clientscripting.internal.IClientObjectAdapter2;
 import org.eclipse.rap.clientscripting.internal.ClientObjectAdapterImpl;
+import org.eclipse.rap.clientscripting.internal.IClientObjectAdapter2;
+import org.eclipse.rap.clientscripting.internal.resources.ClientScriptingResources;
 import org.eclipse.rap.rwt.Adaptable;
 import org.eclipse.rap.rwt.internal.protocol.IClientObjectAdapter;
 import org.eclipse.swt.SWT;
@@ -55,6 +56,7 @@
   protected Collection<ClientListenerBinding> bindings;
 
   public ClientListener( String scriptCode ) {
+    ClientScriptingResources.ensure();
     this.scriptCode = scriptCode;
     disposed = false;
     bindings = new ArrayList<ClientListenerBinding>();
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResource.java
deleted file mode 100644
index c82b8b1..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResource.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-import org.eclipse.rap.ui.resources.IResource;
-
-
-public abstract class ClientScriptingResource implements IResource {
-
-  private static final String PATH_PREFIX = "/org/eclipse/rap/clientscripting/";
-
-  public static final IResource[] ALL_RESOURCES = new IResource[] {
-    new ClientScriptingUtilResource(),
-    new EventBindingAdapterResource(),
-    new EventBindingResource(),
-    new EventProxyResource(),
-    new FunctionResource(),
-    new ListenerAdapterResource(),
-    new SWTResource(),
-    new WidgetProxyResource()
-  };
-
-  private final String location;
-
-  public ClientScriptingResource( String location ) {
-    this.location = PATH_PREFIX + location;
-  }
-
-  public ClassLoader getLoader() {
-    return ClientScriptingResource.class.getClassLoader();
-  }
-
-  public String getLocation() {
-    return location;
-  }
-
-  public boolean isJSLibrary() {
-    return true;
-  }
-
-  public boolean isExternal() {
-    return false;
-  }
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources.java
index c8ea0b1..24f20d3 100644
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources.java
+++ b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources.java
@@ -10,15 +10,21 @@
  ******************************************************************************/
 package org.eclipse.rap.clientscripting.internal.resources;
 
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-
+import java.io.InputStreamReader;
+import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.Application;
+import org.eclipse.rap.rwt.client.service.JavaScriptLoader;
 import org.eclipse.rap.rwt.resources.ResourceLoader;
 
 
 public final class ClientScriptingResources {
 
+  private static final String CHARSET = "UTF-8";
+  private static final String REGISTER_NAME = "clientscripting.js";
   private static final String PREFIX = "org/eclipse/rap/clientscripting/";
   private static final String[] ALL_RESOURCES = {
     "ClientScriptingUtil.js",
@@ -31,23 +37,81 @@
     "WidgetProxy.js"
   };
 
+  public static void ensure() {
+    ensureRegistered();
+    ensureLoaded();
+  }
+
+  private static void ensureRegistered() {
+    if( !RWT.getResourceManager().isRegistered( REGISTER_NAME ) ) {
+      try {
+        register();
+      } catch( IOException exception ) {
+        throw new RuntimeException( "Failed to register resources", exception );
+      }
+    }
+  }
+
+  private static void ensureLoaded() {
+    JavaScriptLoader loader = RWT.getClient().getService( JavaScriptLoader.class );
+    loader.ensure( RWT.getResourceManager().getLocation( REGISTER_NAME ) );
+  }
+
+  private static void register() throws IOException {
+    InputStream inputStream = getConcatentatedInputStream();
+    try {
+      RWT.getResourceManager().register( REGISTER_NAME, inputStream );
+    } finally {
+      inputStream.close();
+    }
+  }
+
   public static void register( Application application ) {
-    ClientscriptingResourceLoader resourceLoader = new ClientscriptingResourceLoader();
+    application.addResource( REGISTER_NAME, new ResourceLoader() {
+      public InputStream getResourceAsStream( String resourceName ) throws IOException {
+        return getConcatentatedInputStream();
+      }
+    } );
+  }
+
+  private static InputStream getConcatentatedInputStream() throws IOException {
+    return new ByteArrayInputStream( concatResources().getBytes( CHARSET ) );
+  }
+
+  private static String concatResources() throws IOException {
+    StringBuilder builder = new StringBuilder();
     for( String resourceName : ALL_RESOURCES ) {
-      application.addResource( resourceName, resourceLoader );
+      InputStream inputStream = getResourceAsStream( resourceName );
+      try {
+        read( inputStream, builder );
+      } finally {
+        inputStream.close();
+      }
+    }
+    return builder.toString();
+  }
+
+  private static InputStream getResourceAsStream( String resourceName ) {
+    ClassLoader classLoader = ClientScriptingResources.class.getClassLoader();
+    InputStream inputStream = classLoader.getResourceAsStream( PREFIX + resourceName );
+    if( inputStream == null ) {
+      throw new RuntimeException( "Resource not found: " + resourceName );
+    }
+    return inputStream;
+  }
+
+  static void read( InputStream inputStream, StringBuilder builder ) throws IOException {
+    InputStreamReader reader = new InputStreamReader( inputStream, CHARSET );
+    BufferedReader bufferedReader = new BufferedReader( reader );
+    char[] buffer = new char[ 4096 ];
+    int read = bufferedReader.read( buffer );
+    while( read != -1 ) {
+      builder.append( buffer, 0, read );
+      read = bufferedReader.read( buffer );
     }
   }
 
   private ClientScriptingResources() {
   }
 
-  private static class ClientscriptingResourceLoader implements ResourceLoader {
-
-    public InputStream getResourceAsStream( String resourceName ) throws IOException {
-      ClassLoader classLoader = ClientScriptingResources.class.getClassLoader();
-      return classLoader.getResourceAsStream( PREFIX + resourceName );
-    }
-
-  }
-
 }
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingUtilResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingUtilResource.java
deleted file mode 100644
index cc59866..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingUtilResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class ClientScriptingUtilResource extends ClientScriptingResource {
-
-  public ClientScriptingUtilResource() {
-    super( "ClientScriptingUtil.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingAdapterResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingAdapterResource.java
deleted file mode 100644
index b476f18..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingAdapterResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class EventBindingAdapterResource extends ClientScriptingResource {
-
-  public EventBindingAdapterResource() {
-    super( "EventBindingAdapter.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingResource.java
deleted file mode 100644
index 5fe1c1a..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventBindingResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class EventBindingResource extends ClientScriptingResource {
-
-  public EventBindingResource() {
-    super( "EventBinding.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventProxyResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventProxyResource.java
deleted file mode 100644
index 4df50fd..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/EventProxyResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class EventProxyResource extends ClientScriptingResource {
-
-  public EventProxyResource() {
-    super( "EventProxy.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/FunctionResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/FunctionResource.java
deleted file mode 100644
index ee0a05a..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/FunctionResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class FunctionResource extends ClientScriptingResource {
-
-  public FunctionResource() {
-    super( "Function.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ListenerAdapterResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ListenerAdapterResource.java
deleted file mode 100644
index 7b5c486..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/ListenerAdapterResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class ListenerAdapterResource extends ClientScriptingResource {
-
-  public ListenerAdapterResource() {
-    super( "ListenerAdapter.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/SWTResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/SWTResource.java
deleted file mode 100644
index 32ed1dc..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/SWTResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class SWTResource extends ClientScriptingResource {
-
-  public SWTResource() {
-    super( "SWT.js" );
-  }
-
-}
diff --git a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/WidgetProxyResource.java b/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/WidgetProxyResource.java
deleted file mode 100644
index e1cf8d9..0000000
--- a/bundles/org.eclipse.rap.clientscripting/src/org/eclipse/rap/clientscripting/internal/resources/WidgetProxyResource.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012 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.internal.resources;
-
-
-public class WidgetProxyResource extends ClientScriptingResource {
-
-  public WidgetProxyResource() {
-    super( "WidgetProxy.js" );
-  }
-
-}
diff --git a/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/ClientScriptingRenderer_Test.java b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/ClientScriptingRenderer_Test.java
index 50935a2..c2d345a 100644
--- a/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/ClientScriptingRenderer_Test.java
+++ b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/ClientScriptingRenderer_Test.java
@@ -10,10 +10,11 @@
  ******************************************************************************/
 package org.eclipse.rap.clientscripting.internal;
 
+import static org.eclipse.rap.clientscripting.internal.ClientObjectUtil.getId;
+import static org.eclipse.rap.clientscripting.test.TestUtil.findBinding;
 import junit.framework.TestCase;
 
 import org.eclipse.rap.clientscripting.ClientListener;
-import org.eclipse.rap.clientscripting.test.TestUtil;
 import org.eclipse.rap.rwt.testfixture.Fixture;
 import org.eclipse.rap.rwt.testfixture.Message;
 import org.eclipse.rap.rwt.testfixture.Message.DestroyOperation;
@@ -41,24 +42,24 @@
   }
 
   public void testCreateListenerNotRenderedBeforeBind() {
-    new ClientListener( "code" );
+    ClientListener listener = new ClientListener( "code" );
 
     ClientScriptingRenderer.render();
 
     Message message = Fixture.getProtocolMessage();
-    assertEquals( 0, message.getOperationCount() );
+    assertNull( message.findCreateOperation( getId( listener ) ) );
   }
 
   public void testCreateListenerAndBindingRendered() {
     ClientListener listener = new ClientListener( "code" );
     listener.addTo( label, ClientListener.KeyUp );
-    ClientListenerBinding binding = TestUtil.findBinding( listener, label, ClientListener.KeyUp );
+    ClientListenerBinding binding = findBinding( listener, label, ClientListener.KeyUp );
 
     ClientScriptingRenderer.render();
 
     Message message = Fixture.getProtocolMessage();
-    assertNotNull( message.findCreateOperation( ClientObjectUtil.getId( listener ) ) );
-    assertNotNull( message.findCreateOperation( ClientObjectUtil.getId( binding ) ) );
+    assertNotNull( message.findCreateOperation( getId( listener ) ) );
+    assertNotNull( message.findCreateOperation( getId( binding ) ) );
   }
 
   public void testCreateRenderedOnlyOnce() {
@@ -76,7 +77,7 @@
   public void testDestroyBindingRendered() {
     ClientListener listener = new ClientListener( "code" );
     listener.addTo( label, ClientListener.KeyUp );
-    ClientListenerBinding binding = TestUtil.findBinding( listener, label, ClientListener.KeyUp );
+    ClientListenerBinding binding = findBinding( listener, label, ClientListener.KeyUp );
     ClientScriptingRenderer.render();
     Fixture.fakeNewRequest();
 
@@ -86,7 +87,7 @@
     Message message = Fixture.getProtocolMessage();
     // TODO [rst] Use Message#findDestroyOperation( String ) as soon as it is available
     DestroyOperation operation = ( DestroyOperation )message.getOperation( 0 );
-    assertEquals( ClientObjectUtil.getId( binding ), operation.getTarget() );
+    assertEquals( getId( binding ), operation.getTarget() );
   }
 
   public void testDestroyBindingRenderedOnlyOnce() {
diff --git a/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources_Test.java b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources_Test.java
new file mode 100644
index 0000000..0ffed34
--- /dev/null
+++ b/tests/org.eclipse.rap.clientscripting.test/src/org/eclipse/rap/clientscripting/internal/resources/ClientScriptingResources_Test.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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.internal.resources;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.endsWith;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.notNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.*;
+
+import org.eclipse.rap.rwt.application.Application;
+import org.eclipse.rap.rwt.client.Client;
+import org.eclipse.rap.rwt.client.service.JavaScriptLoader;
+import org.eclipse.rap.rwt.resources.ResourceLoader;
+import org.eclipse.rap.rwt.resources.ResourceManager;
+import org.eclipse.rap.rwt.testfixture.Fixture;
+import org.mockito.ArgumentCaptor;
+
+import junit.framework.TestCase;
+
+
+public class ClientScriptingResources_Test extends TestCase {
+
+  @Override
+  protected void setUp() throws Exception {
+    Fixture.setUp();
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    Fixture.tearDown();
+  }
+
+  public void testRegistersWithResourceManager() {
+    ResourceManager resourceManager = mock( ResourceManager.class );
+    Fixture.fakeResourceManager( resourceManager );
+
+    ClientScriptingResources.ensure();
+
+    verify( resourceManager ).register( eq( "clientscripting.js" ), ( InputStream )notNull() );
+  }
+
+  public void testDoesNotRegisterWithResourceManagerTwice() {
+    ResourceManager resourceManager = mock( ResourceManager.class );
+    when( Boolean.valueOf( resourceManager.isRegistered( anyString() ) ) ).thenReturn( Boolean.TRUE );
+    Fixture.fakeResourceManager( resourceManager );
+
+    ClientScriptingResources.ensure();
+
+    verify( resourceManager, times( 0 ) ).register( anyString(), any( InputStream.class ) );
+  }
+
+  public void testLoadsJavaScript() {
+    JavaScriptLoader loader = mock( JavaScriptLoader.class );
+    Client client = mock( Client.class );
+    when( client.getService( eq( JavaScriptLoader.class ) ) ).thenReturn( loader );
+    Fixture.fakeClient( client );
+
+    ClientScriptingResources.ensure();
+
+    verify( loader ).ensure( endsWith( "clientscripting.js" ) );
+  }
+
+  public void testRegistersWithApplication() throws IOException {
+    Application application = mock( Application.class );
+
+    ClientScriptingResources.register( application );
+
+    ArgumentCaptor<String> resourceName = ArgumentCaptor.forClass( String.class );
+    ArgumentCaptor<ResourceLoader> resourceLoader = ArgumentCaptor.forClass( ResourceLoader.class );
+    verify( application ).addResource( resourceName.capture(), resourceLoader.capture() );
+
+    assertNotNull( resourceLoader.getValue().getResourceAsStream( resourceName.getValue() ) );
+  }
+
+  public void testReadInputStream() throws IOException {
+    InputStream inputStream = new ByteArrayInputStream( "line1\nline2\n".getBytes() );
+    StringBuilder builder = new StringBuilder();
+
+    ClientScriptingResources.read( inputStream, builder );
+
+    assertEquals( "line1\nline2\n", builder.toString() );
+  }
+
+  public void testReadLongInputStream() throws IOException {
+    String longString = createRandomString( 10000 ); // bigger than buffer size
+    InputStream inputStream = new ByteArrayInputStream( longString.getBytes() );
+    StringBuilder builder = new StringBuilder();
+
+    ClientScriptingResources.read( inputStream, builder );
+
+    assertEquals( longString, builder.toString() );
+  }
+
+  private static String createRandomString( int length ) {
+    String chars = "abcdefghijklmnopqrstuvwxyz";
+    StringBuilder builder = new StringBuilder( length );
+    for( int i = 0; i < length; i++ ) {
+      builder.append( chars.charAt( ( int )( Math.random() * chars.length() ) ) );
+    }
+    return builder.toString();
+  }
+
+}