Use SequenceInputStream to concatenate js resources

Instead of reading resources into strings and concatenate them, use
a sequence input stream. This saves cycles, memory, and code.
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 fa649af..55c5872 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 EclipseSource and others.
+ * Copyright (c) 2012, 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
@@ -10,11 +10,10 @@
  ******************************************************************************/
 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 java.io.SequenceInputStream;
+import java.util.Vector;
 
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.Application;
@@ -24,7 +23,6 @@
 
 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 = {
@@ -75,21 +73,12 @@
     } );
   }
 
-  private static InputStream getConcatentatedInputStream() throws IOException {
-    return new ByteArrayInputStream( concatResources().getBytes( CHARSET ) );
-  }
-
-  private static String concatResources() throws IOException {
-    StringBuilder builder = new StringBuilder();
+  private static InputStream getConcatentatedInputStream() {
+    Vector<InputStream> inputStreams = new Vector<InputStream>( ALL_RESOURCES.length );
     for( String resourceName : ALL_RESOURCES ) {
-      InputStream inputStream = getResourceAsStream( resourceName );
-      try {
-        read( inputStream, builder );
-      } finally {
-        inputStream.close();
-      }
+      inputStreams.add( getResourceAsStream( resourceName ) );
     }
-    return builder.toString();
+    return new SequenceInputStream( inputStreams.elements() );
   }
 
   private static InputStream getResourceAsStream( String resourceName ) {
@@ -101,17 +90,6 @@
     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() {
   }
 
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
index b3bbfcd..3f117e3 100644
--- 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
@@ -15,13 +15,14 @@
 import static org.mockito.Matchers.endsWith;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Matchers.notNull;
+import static org.mockito.Mockito.doAnswer;
 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 java.util.concurrent.atomic.AtomicReference;
 import static org.junit.Assert.*;
 import org.junit.After;
 import org.junit.Before;
@@ -34,6 +35,8 @@
 import org.eclipse.rap.rwt.service.ResourceManager;
 import org.eclipse.rap.rwt.testfixture.Fixture;
 import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 
 public class ClientScriptingResources_Test {
@@ -59,6 +62,41 @@
   }
 
   @Test
+  public void testRegistersConcatenatedResources() {
+    final AtomicReference<String> registeredStringCaptor = new AtomicReference<String>();
+    ResourceManager resourceManager = mock( ResourceManager.class );
+    Fixture.fakeResourceManager( resourceManager );
+    doAnswer( new Answer<Object>() {
+      public Object answer( InvocationOnMock invocation ) throws Throwable {
+        InputStream inputStream = ( InputStream )invocation.getArguments()[1];
+        registeredStringCaptor.set( read( inputStream, "UTF-8" ) );
+        inputStream.close();
+        return null;
+      }
+    } ).when( resourceManager ).register( anyString(), any( InputStream.class ) );
+
+    ClientScriptingResources.ensure();
+
+    String registeredCode = registeredStringCaptor.get();
+    assertTrue( registeredCode.contains( "clientscripting.ClientScriptingUtil =" ) );
+    assertTrue( registeredCode.contains( "clientscripting.EventBinding =" ) );
+    assertTrue( registeredCode.contains( "clientscripting.SWT =" ) );
+    assertTrue( registeredCode.contains( "clientscripting.EventProxy =" ) );
+  }
+
+  static String read( InputStream inputStream, String charset ) throws IOException {
+    InputStreamReader reader = new InputStreamReader( inputStream, charset );
+    StringBuilder builder = new StringBuilder();
+    char[] buffer = new char[ 4096 ];
+    int read = reader.read( buffer );
+    while( read != -1 ) {
+      builder.append( buffer, 0, read );
+      read = reader.read( buffer );
+    }
+    return builder.toString();
+  }
+
+  @Test
   public void testDoesNotRegisterWithResourceManagerTwice() {
     ResourceManager resourceManager = mock( ResourceManager.class );
     when( Boolean.valueOf( resourceManager.isRegistered( anyString() ) ) ).thenReturn( Boolean.TRUE );
@@ -94,34 +132,4 @@
     assertNotNull( resourceLoader.getValue().getResourceAsStream( resourceName.getValue() ) );
   }
 
-  @Test
-  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() );
-  }
-
-  @Test
-  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();
-  }
-
 }