]> source.dussan.org Git - gwtquery.git/commitdiff
Test refactoring. Remove hacked classes used during testing
authorManuel Carrasco Moñino <manuel.carrasco.m@gmail.com>
Mon, 6 Jan 2014 20:22:14 +0000 (21:22 +0100)
committerManuel Carrasco Moñino <manuel.carrasco.m@gmail.com>
Mon, 6 Jan 2014 20:22:14 +0000 (21:22 +0100)
14 files changed:
gwtquery-core/src/main/java/com/google/gwt/query/client/GQ.java
gwtquery-core/src/main/java/com/google/gwt/query/vm/AjaxTransportJre.java
gwtquery-core/src/main/super/com/google/gwt/query/super/com/google/gwt/query/client/GQ.java
gwtquery-core/src/test/java/com/google/gwt/dev/shell/BrowserChannelPatched.java [deleted file]
gwtquery-core/src/test/java/com/google/gwt/junit/RunStyleHtmlUnitPatched.java [deleted file]
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryGwtSuiteTest.java
gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxCommon.java [deleted file]
gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTest.java [deleted file]
gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestGwt.java
gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java [new file with mode: 0644]
gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java [new file with mode: 0644]
gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java [deleted file]
gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestGwt.java
gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java [new file with mode: 0644]

index aa10ce6c123525bae23840a5e99404c92f851239..5120bf3daf9de54d6b23eca16bd3f31850b6fc32 100644 (file)
@@ -26,10 +26,6 @@ import com.google.gwt.user.client.Window;
 
 public abstract class GQ {
   
-  public static String domain = GWT.isClient() 
-      ? (Window.Location.getProtocol() + Window.Location.getHost()) 
-      : "http://127.0.0.1";
-
   private static JsonFactory jsonFactory;
   private static AjaxTransport ajaxTransport;
 
index b5f6d40fbe65fff0a55923d0ebe80cea362d4016..0402004987ad50d1cccc0295c8eadc5b7e8bf4df 100644 (file)
@@ -25,7 +25,10 @@ import com.google.gwt.user.server.Base64Utils;
  */
 public class AjaxTransportJre implements AjaxTransport {
   
-  public AjaxTransportJre() {
+  private static String localDomain = null;
+  
+  public static void enableCORS(String domain) {
+    localDomain = domain;
     System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
   }
   
@@ -83,9 +86,8 @@ public class AjaxTransportJre implements AjaxTransport {
 
   private Response httpClient(Settings s, boolean cors) throws Exception {
     String url = s.getUrl();
-    if (!url.toLowerCase().startsWith("http")) {
-      url = GQ.domain + (url.startsWith("/") ? "" : "/") + url;
-    }
+    assert url.toLowerCase().startsWith("http");
+    
     URL u = new URL(url);
     HttpURLConnection c = (HttpURLConnection) u.openConnection();
     c.setRequestMethod(s.getType());
@@ -94,7 +96,7 @@ public class AjaxTransportJre implements AjaxTransport {
       c.setRequestProperty ("Authorization", "Basic " + Base64Utils.toBase64((s.getUsername() + ":" + s.getPassword()).getBytes()));
     }
     
-    boolean isCORS = cors && !s.getUrl().contains(GQ.domain);
+    boolean isCORS = cors && localDomain != null && !s.getUrl().contains(localDomain);
     if (isCORS) {
       // TODO: fetch options previously to the request
       // >> OPTIONS
@@ -111,7 +113,7 @@ public class AjaxTransportJre implements AjaxTransport {
       // Origin: http://127.0.0.1:8888
       //   Access-Control-Allow-Origin: http://127.0.0.1:8888
       //   Access-Control-Allow-Credentials: true
-      c.setRequestProperty("Origin", GQ.domain);
+      c.setRequestProperty("Origin", localDomain);
     }
     
     if (s.getTimeout() > 0) {
@@ -141,8 +143,8 @@ public class AjaxTransportJre implements AjaxTransport {
     }
     
     int code = c.getResponseCode();
-    if (isCORS && !GQ.domain.equals(c.getHeaderField("Access-Control-Allow-Origin"))) {
-        code = 0;
+    if (isCORS && !localDomain.equals(c.getHeaderField("Access-Control-Allow-Origin"))) {
+      code = 0;
     }
     
     BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
index f421124921bca951b4832cbb603abd166f8949c7..a351fbbe5bf61810f4d54d2786f746b34db88e84 100644 (file)
@@ -27,8 +27,6 @@ import com.google.gwt.user.client.Window;
 
 public class GQ {
   
-  public static final String domain = Window.Location.getHost();
-
   private static JsonFactory jsonFactory;
   private static AjaxTransport ajaxTransport;
 
diff --git a/gwtquery-core/src/test/java/com/google/gwt/dev/shell/BrowserChannelPatched.java b/gwtquery-core/src/test/java/com/google/gwt/dev/shell/BrowserChannelPatched.java
deleted file mode 100644 (file)
index dc357d6..0000000
+++ /dev/null
@@ -1,1720 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.shell;
-
-import com.google.gwt.dev.shell.BrowserChannelPatched.SessionHandler.ExceptionOrReturnValue;
-import com.google.gwt.dev.shell.BrowserChannelPatched.SessionHandler.SpecialDispatchId;
-import com.google.gwt.dev.shell.BrowserChannelPatched.Value.ValueType;
-import com.google.gwt.util.tools.Utility;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.Socket;
-import java.util.Set;
-
-/**
- * 
- */
-public abstract class BrowserChannelPatched {
-
-  /**
-   * An error indicating that the remote side died and we should unroll the
-   * call stack as painlessly as possible to allow cleanup.
-   */
-  public static class RemoteDeathError extends Error {
-
-    public RemoteDeathError(Throwable cause) {
-      super("Remote connection lost", cause);
-    }
-  }
-
-  /**
-   * Class representing a reference to a Java object.
-   */
-  public static class JavaObjectRef implements RemoteObjectRef {
-    private int refId;
-
-    public JavaObjectRef(int refId) {
-      this.refId = refId;
-    }
-
-    public int getRefid() {
-      return Math.abs(refId);
-    }
-
-    @Override
-    public int hashCode() {
-      return refId;
-    }
-
-    public boolean isException() {
-      return refId < 0;
-    }
-
-    @Override
-    public String toString() {
-      return "JavaObjectRef(ref=" + refId + ")";
-    }
-  }
-
-  /**
-   * Class representing a reference to a JS object.
-   */
-  public static class JsObjectRef implements RemoteObjectRef  {
-    
-    private int refId;
-    
-    public JsObjectRef(int refId) {
-      this.refId = refId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      return (o instanceof JsObjectRef) && ((JsObjectRef) o).refId == refId;
-    }
-
-    public int getRefid() {
-      // exceptions are negative, so we get the absolute value
-      return Math.abs(refId);
-    }
-
-    @Override
-    public int hashCode() {
-      return refId;
-    }
-
-    public boolean isException() {
-      return refId < 0;
-    }
-
-    @Override
-    public String toString() {
-      return "JsObjectRef(" + refId + ")";
-    }
-  }
-
-  /**
-   * Enumeration of message type ids.
-   * 
-   * <p>Ids are used instead of relying on the ordinal to avoid sychronization
-   * problems with the client.
-   */
-  public enum MessageType {
-    /**
-     * A message to invoke a method on the other side of the wire.  Note that
-     * the messages are asymmetric -- see {@link InvokeOnClientMessage} and
-     * {@link InvokeOnServerMessage}.
-     */
-    INVOKE(0),
-    
-    /**
-     * Returns the result of an INVOKE, INVOKE_SPECIAL, or LOAD_MODULE message. 
-     */
-    RETURN(1),
-    
-    /**
-     * v1 LOAD_MODULE message.
-     */
-    OLD_LOAD_MODULE(2),
-    
-    /**
-     * Normal closure of the connection.
-     */
-    QUIT(3),
-    
-    /**
-     * A request by the server to load JSNI source into the client's JS engine.
-     */
-    LOAD_JSNI(4),
-    
-    INVOKE_SPECIAL(5),
-    
-    FREE_VALUE(6),
-    
-    /**
-     * Abnormal termination of the connection.
-     */
-    FATAL_ERROR(7),
-    
-    CHECK_VERSIONS(8),
-    
-    PROTOCOL_VERSION(9),
-    
-    CHOOSE_TRANSPORT(10),
-    
-    SWITCH_TRANSPORT(11),
-    
-    LOAD_MODULE(12),
-    
-    REQUEST_ICON(13),
-    
-    USER_AGENT_ICON(14),
-    
-    REQUEST_PLUGIN(15);
-    
-    private final int id;
-    
-    private MessageType(int id) {
-      this.id = id;
-    }
-    
-    public int getId() {
-      return id;
-    }
-  }
-
-  /**
-   * Represents an object on the other side of the channel, known to this side
-   * by an reference ID.
-   */
-  public interface RemoteObjectRef {
-    
-    /**
-      * @return the reference ID for this object.
-      */
-    int getRefid();
-  }
-
-  /**
-   * Hook interface for responding to messages.
-   */
-  public abstract static class SessionHandler<T extends BrowserChannelPatched> {
-
-    /**
-     * Wrapper to return both a return value/exception and a flag as to whether
-     * an exception was thrown or not.
-     */
-    public static class ExceptionOrReturnValue {
-      private final boolean isException;
-      private final Value returnValue;
-
-      public ExceptionOrReturnValue(boolean isException, Value returnValue) {
-        this.isException = isException;
-        this.returnValue = returnValue;
-      }
-
-      public Value getReturnValue() {
-        return returnValue;
-      }
-
-      public boolean isException() {
-        return isException;
-      }
-    }
-
-    /**
-     * Enumeration of dispatch IDs on object 0 (the ServerMethods object).
-     * 
-     * <p>Ids are set specifically rather than relying on the ordinal to avoid
-     * synchronization problems with the client.
-     * 
-     * TODO: hasMethod/hasProperty no longer used, remove them!
-     */
-    public enum SpecialDispatchId {
-      HasMethod(0), HasProperty(1), GetProperty(2), SetProperty(3);
-      
-      private final int id;
-
-      private SpecialDispatchId(int id) {
-        this.id = id;
-      }
-      
-      public int getId() {
-        return id;
-      }
-    }
-
-    public abstract void freeValue(T channel, int[] ids);
-  }
-
-  /**
-   * Represents a value for BrowserChannel.
-   */
-  public static class Value {
-    /**
-     * Enum of type tags sent across the wire.
-     */
-    public enum ValueType {
-      /**
-       * Primitive values.
-       */
-      NULL(0), BOOLEAN(1), BYTE(2), CHAR(3), SHORT(4), INT(5), LONG(6),
-      FLOAT(7), DOUBLE(8), STRING(9),
-
-      /**
-       * Representations of Java or JS objects, sent as an index into a table
-       * kept on the side holding the actual object.
-       */
-      JAVA_OBJECT(10), JS_OBJECT(11),
-
-      /**
-       * A Javascript undef value, also used for void returns.
-       */
-      UNDEFINED(12);
-
-      private final int id;
-
-      private ValueType(int id) {
-        this.id = id;
-      }
-
-      byte getTag() {
-        return (byte) id;
-      }
-    }
-
-    /**
-     * Type tag value.
-     */
-    private ValueType type = ValueType.UNDEFINED;
-
-    /**
-     * Represents a value sent/received across the wire.
-     */
-    private Object value = null;
-
-    public Value() {
-    }
-
-    public Value(Object obj) {
-      convertFromJavaValue(obj);
-    }
-
-    /**
-     * Convert a Java object to a value. Objects must be primitive wrappers,
-     * Strings, or JsObjectRef/JavaObjectRef instances.
-     * 
-     * @param obj value to convert.
-     */
-    public void convertFromJavaValue(Object obj) {
-      if (obj == null) {
-        type = ValueType.NULL;
-      } else if (obj instanceof Boolean) {
-        type = ValueType.BOOLEAN;
-      } else if (obj instanceof Byte) {
-        type = ValueType.BYTE;
-      } else if (obj instanceof Character) {
-        type = ValueType.CHAR;
-      } else if (obj instanceof Double) {
-        type = ValueType.DOUBLE;
-      } else if (obj instanceof Float) {
-        type = ValueType.FLOAT;
-      } else if (obj instanceof Integer) {
-        type = ValueType.INT;
-      } else if (obj instanceof Long) {
-        type = ValueType.LONG;
-      } else if (obj instanceof Short) {
-        type = ValueType.SHORT;
-      } else if (obj instanceof String) {
-        type = ValueType.STRING;
-      } else if (obj instanceof JsObjectRef) {
-        // TODO: exception handling?
-        type = ValueType.JS_OBJECT;
-      } else if (obj instanceof JavaObjectRef) {
-        // TODO: exception handling?
-        type = ValueType.JAVA_OBJECT;
-      } else {
-        type = ValueType.STRING;
-        obj = String.valueOf(obj);
-//        throw new RuntimeException(
-//            "Unexpected Java type in convertFromJavaValue: " + obj.getClass() + " " + obj);
-      }
-      value = obj;
-    }
-
-    /**
-     * Convert a value to the requested Java type.
-     * 
-     * @param reqType type to convert to
-     * @return value as that type.
-     */
-    public Object convertToJavaType(Class<?> reqType) {
-      if (reqType.isArray()) {
-        // TODO(jat): handle arrays?
-      }
-      if (reqType.equals(Boolean.class)) {
-        assert type == ValueType.BOOLEAN;
-        return value;
-      } else if (reqType.equals(Byte.class) || reqType.equals(byte.class)) {
-        assert isNumber();
-        return Byte.valueOf(((Number) value).byteValue());
-      } else if (reqType.equals(Character.class) || reqType.equals(char.class)) {
-        if (type == ValueType.CHAR) {
-          return value;
-        } else {
-          assert isNumber();
-          return Character.valueOf((char) ((Number) value).shortValue());
-        }
-      } else if (reqType.equals(Double.class) || reqType.equals(double.class)) {
-        assert isNumber();
-        return Double.valueOf(((Number) value).doubleValue());
-      } else if (reqType.equals(Float.class) || reqType.equals(float.class)) {
-        assert isNumber();
-        return Float.valueOf(((Number) value).floatValue());
-      } else if (reqType.equals(Integer.class) || reqType.equals(int.class)) {
-        assert isNumber();
-        return Integer.valueOf(((Number) value).intValue());
-      } else if (reqType.equals(Long.class) || reqType.equals(long.class)) {
-        assert isNumber();
-        return Long.valueOf(((Number) value).longValue());
-      } else if (reqType.equals(Short.class) || reqType.equals(short.class)) {
-        assert isNumber();
-        return Short.valueOf(((Number) value).shortValue());
-      } else if (reqType.equals(String.class)) {
-        assert type == ValueType.STRING;
-        return value;
-      } else {
-        // Wants an object, caller must deal with object references.
-        return value;
-      }
-    }
-
-    public boolean getBoolean() {
-      assert type == ValueType.BOOLEAN;
-      return ((Boolean) value).booleanValue();
-    }
-
-    public byte getByte() {
-      assert type == ValueType.BYTE;
-      return ((Byte) value).byteValue();
-    }
-
-    public char getChar() {
-      assert type == ValueType.CHAR;
-      return ((Character) value).charValue();
-    }
-
-    public double getDouble() {
-      assert type == ValueType.DOUBLE;
-      return ((Double) value).doubleValue();
-    }
-
-    public float getFloat() {
-      assert type == ValueType.FLOAT;
-      return ((Float) value).floatValue();
-    }
-
-    public int getInt() {
-      assert type == ValueType.INT;
-      return ((Integer) value).intValue();
-    }
-
-    public JavaObjectRef getJavaObject() {
-      assert type == ValueType.JAVA_OBJECT;
-      return (JavaObjectRef) value;
-    }
-
-    public JsObjectRef getJsObject() {
-      assert type == ValueType.JS_OBJECT;
-      return (JsObjectRef) value;
-    }
-
-    public long getLong() {
-      assert type == ValueType.LONG;
-      return ((Long) value).longValue();
-    }
-
-    public short getShort() {
-      assert type == ValueType.SHORT;
-      return ((Short) value).shortValue();
-    }
-
-    public String getString() {
-      assert type == ValueType.STRING;
-      return (String) value;
-    }
-
-    public ValueType getType() {
-      return type;
-    }
-
-    public Object getValue() {
-      return value;
-    }
-
-    public boolean isBoolean() {
-      return type == ValueType.BOOLEAN;
-    }
-
-    public boolean isByte() {
-      return type == ValueType.BYTE;
-    }
-
-    public boolean isChar() {
-      return type == ValueType.CHAR;
-    }
-
-    public boolean isDouble() {
-      return type == ValueType.DOUBLE;
-    }
-
-    public boolean isFloat() {
-      return type == ValueType.FLOAT;
-    }
-
-    public boolean isInt() {
-      return type == ValueType.INT;
-    }
-
-    public boolean isJavaObject() {
-      return type == ValueType.JAVA_OBJECT;
-    }
-
-    public boolean isJsObject() {
-      return type == ValueType.JS_OBJECT;
-    }
-
-    public boolean isLong() {
-      return type == ValueType.LONG;
-    }
-
-    public boolean isNull() {
-      return type == ValueType.NULL;
-    }
-
-    public boolean isNumber() {
-      switch (type) {
-        case BYTE:
-        case CHAR:
-        case DOUBLE:
-        case FLOAT:
-        case INT:
-        case LONG:
-        case SHORT:
-          return true;
-        default:
-          return false;
-      }
-    }
-
-    public boolean isPrimitive() {
-      switch (type) {
-        case BOOLEAN:
-        case BYTE:
-        case CHAR:
-        case DOUBLE:
-        case FLOAT:
-        case INT:
-        case LONG:
-        case SHORT:
-          return true;
-        default:
-          return false;
-      }
-    }
-
-    public boolean isShort() {
-      return type == ValueType.SHORT;
-    }
-
-    public boolean isString() {
-      return type == ValueType.STRING;
-    }
-
-    public boolean isUndefined() {
-      return type == ValueType.UNDEFINED;
-    }
-
-    public void setBoolean(boolean val) {
-      type = ValueType.BOOLEAN;
-      value = Boolean.valueOf(val);
-    }
-
-    public void setByte(byte val) {
-      type = ValueType.BYTE;
-      value = Byte.valueOf(val);
-    }
-
-    public void setChar(char val) {
-      type = ValueType.CHAR;
-      value = Character.valueOf(val);
-    }
-
-    public void setDouble(double val) {
-      type = ValueType.DOUBLE;
-      value = Double.valueOf(val);
-    }
-
-    public void setFloat(float val) {
-      type = ValueType.FLOAT;
-      value = Float.valueOf(val);
-    }
-
-    public void setInt(int val) {
-      type = ValueType.INT;
-      value = Integer.valueOf(val);
-    }
-
-    public void setJavaObject(JavaObjectRef val) {
-      type = ValueType.JAVA_OBJECT;
-      value = val;
-    }
-
-    public void setJsObject(JsObjectRef val) {
-      type = ValueType.JS_OBJECT;
-      value = val;
-    }
-
-    public void setLong(long val) {
-      type = ValueType.BOOLEAN;
-      value = Long.valueOf(val);
-    }
-
-    public void setNull() {
-      type = ValueType.NULL;
-      value = null;
-    }
-
-    public void setShort(short val) {
-      type = ValueType.SHORT;
-      value = Short.valueOf(val);
-    }
-
-    public void setString(String val) {
-      type = ValueType.STRING;
-      value = val;
-    }
-
-    public void setUndefined() {
-      type = ValueType.UNDEFINED;
-      value = null;
-    }
-
-    @Override
-    public String toString() {
-      return type + ": " + value;
-    }
-  }
-
-  /**
-   * The initial request from the client, supplies a range of supported versions
-   * and the version from hosted.html (so stale copies on an external server
-   * can be detected).
-   */
-  protected static class CheckVersionsMessage extends Message {
-    
-    public static CheckVersionsMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int minVersion = stream.readInt();
-      int maxVersion = stream.readInt();
-      String hostedHtmlVersion = readUtf8String(stream);
-      return new CheckVersionsMessage(channel, minVersion, maxVersion,
-          hostedHtmlVersion);
-    }
-
-    private final String hostedHtmlVersion;
-
-    private final int maxVersion;
-
-    private final int minVersion;
-
-    public CheckVersionsMessage(BrowserChannelPatched channel, int minVersion,
-        int maxVersion, String hostedHtmlVersion) {
-      super(channel);
-      this.minVersion = minVersion;
-      this.maxVersion = maxVersion;
-      this.hostedHtmlVersion = hostedHtmlVersion;
-    }
-
-    public String getHostedHtmlVersion() {
-      return hostedHtmlVersion;
-    }
-
-    public int getMaxVersion() {
-      return maxVersion;
-    }
-
-    public int getMinVersion() {
-      return minVersion;
-    }
-
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.CHECK_VERSIONS.getId());
-      stream.writeInt(minVersion);
-      stream.writeInt(maxVersion);
-      writeUtf8String(stream, hostedHtmlVersion);
-      stream.flush();
-    }
-  }
-
-  /**
-   * A message from the client giving a list of supported connection methods
-   * and requesting the server choose one of them to switch protocol traffic to.
-   */
-  protected static class ChooseTransportMessage extends Message {
-    
-    public static ChooseTransportMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int n = stream.readInt();
-      String[] transports = new String[n];
-      for (int i = 0; i < n; ++i) {
-        transports[i] = readUtf8String(stream);
-      }
-      return new ChooseTransportMessage(channel, transports);
-    }
-
-    private final String[] transports;
-
-    public ChooseTransportMessage(BrowserChannelPatched channel,
-        String[] transports) {
-      super(channel);
-      this.transports = transports;
-    }
-
-    public String[] getTransports() {
-      return transports;
-    }
-    
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.CHOOSE_TRANSPORT.getId());
-      stream.writeInt(transports.length);
-      for (String transport : transports) {
-        writeUtf8String(stream, transport);
-      }
-    }
-  }
-
-  /**
-   * A message reporting a connection error to the client.
-   */
-  protected static class FatalErrorMessage extends Message {
-
-    public static FatalErrorMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      // NOTE: Tag has already been read.
-      String error = readUtf8String(stream);
-      return new FatalErrorMessage(channel, error);
-    }
-
-    private final String error;
-
-    public FatalErrorMessage(BrowserChannelPatched channel, String error) {
-      super(channel);
-      this.error = error;
-    }
-    
-    public String getError() {
-      return error;
-    }
-    
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.FATAL_ERROR.getId());
-      writeUtf8String(stream, error);
-    }
-  }
-
-  /**
-   * A message asking the other side to free object references. Note that there
-   * is no response to this message, and this must only be sent immediately
-   * before an Invoke or Return message.
-   */
-  protected static class FreeMessage extends Message {
-    public static FreeMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int numIds = stream.readInt();
-      // TODO: sanity check id count
-      int ids[] = new int[numIds];
-      for (int i = 0; i < numIds; ++i) {
-        ids[i] = stream.readInt();
-      }
-      return new FreeMessage(channel, ids);
-    }
-
-    public static void send(BrowserChannelPatched channel, int[] ids)
-        throws IOException {
-      DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.FREE_VALUE.getId());
-      stream.writeInt(ids.length);
-      for (int id : ids) {
-        stream.writeInt(id);
-      }
-      stream.flush();
-    }
-
-    private final int ids[];
-
-    public FreeMessage(BrowserChannelPatched channel, int[] ids) {
-      super(channel);
-      this.ids = ids;
-    }
-
-    public int[] getIds() {
-      return ids;
-    }
-
-    @Override
-    public boolean isAsynchronous() {
-      return true;
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel(), ids);
-    }
-  }
-
-  /**
-   * A request from the server to invoke a function on the client.
-   * 
-   * Note that MessageType.INVOKE can refer to either this class
-   * or {@link InvokeOnServerMessage} depending on the direction, as the
-   * protocol is asymmetric (Java needs a dispatch ID, Javascript needs a
-   * name).
-   */
-  protected static class InvokeOnClientMessage extends Message {
-    public static InvokeOnClientMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      // NOTE: Tag has already been read.
-      String methodName = readUtf8String(stream);
-      Value thisRef = channel.readValue(stream);
-      int argLen = stream.readInt();
-      Value[] args = new Value[argLen];
-      for (int i = 0; i < argLen; i++) {
-        args[i] = channel.readValue(stream);
-      }
-      return new InvokeOnClientMessage(channel, methodName, thisRef, args);
-    }
-
-    private final Value[] args;
-    private final String methodName;
-    private final Value thisRef;
-
-    public InvokeOnClientMessage(BrowserChannelPatched channel, String methodName,
-        Value thisRef, Value[] args) {
-      super(channel);
-      this.thisRef = thisRef;
-      this.methodName = methodName;
-      this.args = args;
-    }
-
-    public Value[] getArgs() {
-      return args;
-    }
-
-    public String getMethodName() {
-      return methodName;
-    }
-
-    public Value getThis() {
-      return thisRef;
-    }
-
-    @Override
-    public void send() throws IOException {
-      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-
-      stream.writeByte(MessageType.INVOKE.getId());
-      writeUtf8String(stream, methodName);
-      getBrowserChannel().writeValue(stream, thisRef);
-      stream.writeInt(args.length);
-      for (int i = 0; i < args.length; i++) {
-        getBrowserChannel().writeValue(stream, args[i]);
-      }
-      stream.flush();
-    }
-  }
-
-  /**
-   * A request from the client to invoke a function on the server.
-   * 
-   * Note that MessageType.INVOKE can refer to either this class
-   * or {@link InvokeOnClientMessage} depending on the direction, as the
-   * protocol is asymmetric (Java needs a dispatch ID, Javascript needs a
-   * name).
-   */
-  protected static class InvokeOnServerMessage extends Message {
-    public static InvokeOnServerMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      // NOTE: Tag has already been read.
-      int methodDispatchId = stream.readInt();
-      Value thisRef = channel.readValue(stream);
-      int argLen = stream.readInt();
-      Value[] args = new Value[argLen];
-      for (int i = 0; i < argLen; i++) {
-        args[i] = channel.readValue(stream);
-      }
-      return new InvokeOnServerMessage(channel, methodDispatchId, thisRef,
-          args);
-    }
-
-    private final Value[] args;
-    private final int methodDispatchId;
-    private final Value thisRef;
-
-    public InvokeOnServerMessage(BrowserChannelPatched channel, int methodDispatchId,
-        Value thisRef, Value[] args) {
-      super(channel);
-      this.thisRef = thisRef;
-      this.methodDispatchId = methodDispatchId;
-      this.args = args;
-    }
-
-    public Value[] getArgs() {
-      return args;
-    }
-
-    public int getMethodDispatchId() {
-      return methodDispatchId;
-    }
-
-    public Value getThis() {
-      return thisRef;
-    }
-
-    @Override
-    public void send() throws IOException {
-      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-
-      stream.writeByte(MessageType.INVOKE.getId());
-      stream.writeInt(methodDispatchId);
-      getBrowserChannel().writeValue(stream, thisRef);
-      stream.writeInt(args.length);
-      for (int i = 0; i < args.length; i++) {
-        getBrowserChannel().writeValue(stream, args[i]);
-      }
-      stream.flush();
-    }
-  }
-
-  /**
-   * A request from the to invoke a function on the other side.
-   */
-  protected static class InvokeSpecialMessage extends Message {
-    public static InvokeSpecialMessage receive(BrowserChannelPatched channel)
-        throws IOException, BrowserChannelException {
-      final DataInputStream stream = channel.getStreamFromOtherSide();
-      // NOTE: Tag has already been read.
-      final int specialMethodInt = stream.readByte();
-      SpecialDispatchId[] ids = SpecialDispatchId.values();
-      if (specialMethodInt < 0 || specialMethodInt >= ids.length) {
-        throw new BrowserChannelException("Invalid dispatch id "
-            + specialMethodInt);
-      }
-      final SpecialDispatchId dispatchId = ids[specialMethodInt];
-      final int argLen = stream.readInt();
-      final Value[] args = new Value[argLen];
-      for (int i = 0; i < argLen; i++) {
-        args[i] = channel.readValue(stream);
-      }
-      return new InvokeSpecialMessage(channel, dispatchId, args);
-    }
-
-    private final Value[] args;
-    private final SpecialDispatchId dispatchId;
-
-    public InvokeSpecialMessage(BrowserChannelPatched channel,
-        SpecialDispatchId dispatchId, Value[] args) {
-      super(channel);
-      this.dispatchId = dispatchId;
-      this.args = args;
-    }
-
-    public Value[] getArgs() {
-      return args;
-    }
-
-    public SpecialDispatchId getDispatchId() {
-      return dispatchId;
-    }
-
-    @Override
-    public void send() throws IOException {
-      final DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-
-      stream.writeByte(MessageType.INVOKE_SPECIAL.getId());
-      stream.writeByte(dispatchId.getId());
-      stream.writeInt(args.length);
-      for (int i = 0; i < args.length; i++) {
-        getBrowserChannel().writeValue(stream, args[i]);
-      }
-      stream.flush();
-    }
-  }
-
-  /**
-   * A message sending JSNI code to be evaluated. Note that there is no response
-   * to this message, and this must only be sent immediately before an Invoke or
-   * Return message.
-   */
-  protected static class LoadJsniMessage extends Message {
-    public static LoadJsniMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      String js = readUtf8String(stream);
-      return new LoadJsniMessage(channel, js);
-    }
-
-    public static void send(BrowserChannelPatched channel, String js)
-        throws IOException {
-      DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.write(MessageType.LOAD_JSNI.getId());
-      writeUtf8String(stream, js);
-      stream.flush();
-    }
-
-    private final String js;
-
-    public LoadJsniMessage(BrowserChannelPatched channel, String js) {
-      super(channel);
-      this.js = js;
-    }
-
-    public String getJsni() {
-      return js;
-    }
-
-    @Override
-    public boolean isAsynchronous() {
-      return true;
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel(), js);
-    }
-  }
-
-  /**
-   * A request from the client that the server load and initialize a given
-   * module.
-   */
-  protected static class LoadModuleMessage extends Message {
-    public static LoadModuleMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      String url = readUtf8String(stream);
-      String tabKey = readUtf8String(stream);
-      String sessionKey = readUtf8String(stream);
-      String moduleName = readUtf8String(stream);
-      String userAgent = readUtf8String(stream);
-      return new LoadModuleMessage(channel, url, tabKey, sessionKey, moduleName,
-          userAgent);
-    }
-
-    private final String moduleName;
-
-    private final String sessionKey;
-
-    private final String tabKey;
-    
-    private final String url;
-
-    private final String userAgent;
-
-    /**
-     * Creates a LoadModule message to be sent to the server.
-     * 
-     * @param channel BrowserChannel instance
-     * @param url URL of main top-level window - may not be null
-     * @param tabKey opaque key identifying the tab in the browser, or an
-     *     empty string if it cannot be determined - may not be null
-     * @param sessionKey opaque key identifying a particular session (ie,
-     *     group of modules) - may not be null
-     * @param moduleName name of GWT module to load - may not be null
-     * @param userAgent user agent identifier of the browser - may not be null
-     */
-    public LoadModuleMessage(BrowserChannelPatched channel, String url,
-        String tabKey, String sessionKey, String moduleName, String userAgent) {
-      super(channel);
-      assert url != null;
-      assert tabKey != null;
-      assert sessionKey != null;
-      assert moduleName != null;
-      assert userAgent != null;
-      this.url = url;
-      this.tabKey = tabKey;
-      this.sessionKey = sessionKey;
-      this.moduleName = moduleName;
-      this.userAgent = userAgent;
-    }
-
-    public String getModuleName() {
-      return moduleName;
-    }
-
-    public String getSessionKey() {
-      return sessionKey;
-    }
-
-    public String getTabKey() {
-      return tabKey;
-    }
-
-    public String getUrl() {
-      return url;
-    }
-
-    public String getUserAgent() {
-      return userAgent;
-    }
-
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.LOAD_MODULE.getId());
-      writeUtf8String(stream, url);
-      writeUtf8String(stream, tabKey);
-      writeUtf8String(stream, sessionKey);
-      writeUtf8String(stream, moduleName);
-      writeUtf8String(stream, userAgent);
-      stream.flush();
-    }
-  }
-
-  /**
-   * Abstract base class of OOPHM messages.
-   */
-  protected abstract static class Message {
-    public static MessageType readMessageType(DataInputStream stream)
-        throws IOException, BrowserChannelException {
-      stream.mark(1);
-      int type = stream.readByte();
-      MessageType[] types = MessageType.values();
-      if (type < 0 || type >= types.length) {
-        stream.reset();
-        throw new BrowserChannelException("Invalid message type " + type);
-      }
-      return types[type];
-    }
-
-    private final BrowserChannelPatched channel;
-
-    public Message(BrowserChannelPatched channel) {
-      this.channel = channel;
-    }
-
-    public final BrowserChannelPatched getBrowserChannel() {
-      return channel;
-    }
-
-    /**
-     * @return true if this message type is asynchronous and does not expect a
-     *         return message.
-     */
-    public boolean isAsynchronous() {
-      return false;
-    }
-
-    /**
-     * @throws IOException if a subclass encounters an I/O error
-     */
-    public void send() throws IOException {
-      throw new UnsupportedOperationException(getClass().getName()
-          + " is a message format that can only be received.");
-    }
-  }
-
-  /**
-   * Provides a way of allocating JS and Java object ids without knowing
-   * which one is the remote type, so code can be shared between client and
-   * server.
-   */
-  protected interface ObjectRefFactory {
-
-    JavaObjectRef getJavaObjectRef(int refId);
-
-    JsObjectRef getJsObjectRef(int refId);
-
-    Set<Integer> getRefIdsForCleanup();
-  }
-
-  /**
-   * A request from the client that the server load and initialize a given
-   * module (original v1 version).
-   */
-  protected static class OldLoadModuleMessage extends Message {
-    public static OldLoadModuleMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int protoVersion = stream.readInt();
-      String moduleName = readUtf8String(stream);
-      String userAgent = readUtf8String(stream);
-      return new OldLoadModuleMessage(channel, protoVersion, moduleName,
-          userAgent);
-    }
-
-    private final String moduleName;
-
-    private final int protoVersion;
-
-    private final String userAgent;
-    
-    public OldLoadModuleMessage(BrowserChannelPatched channel, int protoVersion,
-        String moduleName, String userAgent) {
-      super(channel);
-      this.protoVersion = protoVersion;
-      this.moduleName = moduleName;
-      this.userAgent = userAgent;
-    }
-
-    public String getModuleName() {
-      return moduleName;
-    }
-
-    public int getProtoVersion() {
-      return protoVersion;
-    }
-
-    public String getUserAgent() {
-      return userAgent;
-    }
-
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.OLD_LOAD_MODULE.getId());
-      stream.writeInt(protoVersion);
-      writeUtf8String(stream, moduleName);
-      writeUtf8String(stream, userAgent);
-      stream.flush();
-    }
-  }
-
-  /**
-   * Reports the selected protocol version.
-   */
-  protected static class ProtocolVersionMessage extends Message {
-    
-    public static ProtocolVersionMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int protocolVersion = stream.readInt();
-      return new ProtocolVersionMessage(channel, protocolVersion);
-    }
-
-    private final int protocolVersion;
-
-    public ProtocolVersionMessage(BrowserChannelPatched channel, int protocolVersion) {
-      super(channel);
-      this.protocolVersion = protocolVersion;
-    }
-
-    public int getProtocolVersion() {
-      return protocolVersion;
-    }
-
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.PROTOCOL_VERSION.getId());
-      stream.writeInt(protocolVersion);
-      stream.flush();
-    }
-  }
-
-  /**
-   * A message signifying a soft close of the communications channel.
-   */
-  protected static class QuitMessage extends Message {
-    public static QuitMessage receive(BrowserChannelPatched channel) {
-      return new QuitMessage(channel);
-    }
-
-    public static void send(BrowserChannelPatched channel) throws IOException {
-      final DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.QUIT.getId());
-      stream.flush();
-    }
-
-    public QuitMessage(BrowserChannelPatched channel) {
-      super(channel);
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel());
-    }
-  }
-
-  /**
-   * A message asking the client to send an icon suitable for use in the UI.
-   * <p>See {@link UserAgentIconMessage}.
-   */
-  protected static class RequestIconMessage extends Message {
-
-    /**
-     * Receive a RequestIconMessage, assuming the message tag has already been
-     * read.
-     * 
-     * @throws IOException
-     */
-    public static RequestIconMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      return new RequestIconMessage(channel);
-    }
-
-    public static void send(BrowserChannelPatched channel)
-        throws IOException {
-      DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.REQUEST_ICON.getId());
-      stream.flush();
-    }
-
-    public RequestIconMessage(BrowserChannelPatched channel) {
-      super(channel);
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel());
-    }
-  }
-
-  /**
-   * Signifies a return from a previous invoke.
-   */
-  protected static class ReturnMessage extends Message {
-    public static ReturnMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      final DataInputStream stream = channel.getStreamFromOtherSide();
-      final boolean isException = stream.readBoolean();
-      final Value returnValue = channel.readValue(stream);
-      return new ReturnMessage(channel, isException, returnValue);
-    }
-
-    public static void send(BrowserChannelPatched channel, boolean isException,
-        Value returnValue) throws IOException {
-      final DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.RETURN.getId());
-      stream.writeBoolean(isException);
-      channel.writeValue(stream, returnValue);
-      stream.flush();
-    }
-
-    public static void send(BrowserChannelPatched channel,
-        ExceptionOrReturnValue returnOrException) throws IOException {
-      send(channel, returnOrException.isException(),
-          returnOrException.getReturnValue());
-    }
-
-    private final boolean isException;
-    private final Value returnValue;
-
-    public ReturnMessage(BrowserChannelPatched channel, boolean isException,
-        Value returnValue) {
-      super(channel);
-      this.returnValue = returnValue;
-      this.isException = isException;
-    }
-
-    public Value getReturnValue() {
-      return returnValue;
-    }
-
-    public boolean isException() {
-      return isException;
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel(), isException, returnValue);
-    }
-  }
-
-  /**
-   * A response to ChooseTransport telling the client which transport should
-   * be used for the remainder of the protocol. 
-   */
-  protected static class SwitchTransportMessage extends Message {
-    
-    public static SwitchTransportMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      String transport = readUtf8String(stream);
-      String transportArgs = readUtf8String(stream);
-      return new SwitchTransportMessage(channel, transport, transportArgs);
-    }
-
-    private final String transport;
-
-    private final String transportArgs;
-
-    public SwitchTransportMessage(BrowserChannelPatched channel,
-        String transport, String transportArgs) {
-      super(channel);
-      // Change nulls to empty strings
-      if (transport == null) {
-        transport = "";
-      }
-      if (transportArgs == null) {
-        transportArgs = "";
-      }
-      this.transport = transport;
-      this.transportArgs = transportArgs;
-    }
-    
-    public String getTransport() {
-      return transport;
-    }
-
-    public String getTransportArgs() {
-      return transportArgs;
-    }
-    
-    @Override
-    public void send() throws IOException {
-      DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.SWITCH_TRANSPORT.getId());
-      writeUtf8String(stream, transport);
-      writeUtf8String(stream, transportArgs);
-      stream.flush();
-    }
-  }
-
-  /**
-   * A message supplying an icon, which fits in 24x24 and in a standard image
-   * format such as PNG or GIF, suitable for use in the UI.
-   * <p>See {@link RequestIconMessage}.
-   */
-  protected static class UserAgentIconMessage extends Message {
-    public static UserAgentIconMessage receive(BrowserChannelPatched channel)
-        throws IOException {
-      byte[] iconBytes = null;
-      DataInputStream stream = channel.getStreamFromOtherSide();
-      int len = stream.readInt();
-      if (len > 0) {
-        iconBytes = new byte[len];
-        for (int i = 0; i < len; ++i) {
-          iconBytes[i] = stream.readByte();
-        }
-      }
-      return new UserAgentIconMessage(channel, iconBytes);
-    }
-
-    public static void send(BrowserChannelPatched channel, byte[] iconBytes)
-        throws IOException {
-      DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.USER_AGENT_ICON.getId());
-      if (iconBytes == null) {
-        stream.writeInt(0);
-      } else {
-        stream.writeInt(iconBytes.length);
-        for (byte b : iconBytes) {
-          stream.writeByte(b);
-        }
-      }
-      stream.flush();
-    }
-
-    private byte[] iconBytes;
-
-    public UserAgentIconMessage(BrowserChannelPatched channel, byte[] iconBytes) {
-      super(channel);
-      this.iconBytes = iconBytes;
-    }
-
-    public byte[] getIconBytes() {
-      return iconBytes;
-    }
-
-    @Override
-    public void send() throws IOException {
-      send(getBrowserChannel(), iconBytes);
-    }
-  }
-
-  /**
-   * The current version of the protocol.
-   */
-  public static final int PROTOCOL_VERSION_CURRENT = 3;
-
-  /**
-   * The oldest protocol version supported by this code.
-   */
-  public static final int PROTOCOL_VERSION_OLDEST = 2;
-  
-  /**
-   * The protocol version that added the GetIcon message.
-   */
-  public static final int PROTOCOL_VERSION_GET_ICON = 3;
-  
-  public static final int SPECIAL_CLIENTMETHODS_OBJECT = 0;
-
-  public static final int SPECIAL_SERVERMETHODS_OBJECT = 0;
-
-  protected static JavaObjectRef getJavaObjectRef(int refId) {
-    return new JavaObjectRef(refId);
-  }
-
-  protected static String readUtf8String(DataInputStream stream)
-      throws IOException {
-    final int len = stream.readInt();
-    final byte[] data = new byte[len];
-    stream.readFully(data);
-    return new String(data, "UTF8");
-  }
-
-  protected static ValueType readValueType(DataInputStream stream)
-      throws IOException, BrowserChannelException {
-    int type = stream.readByte();
-    ValueType[] types = ValueType.values();
-    if (type < 0 || type >= types.length) {
-      throw new BrowserChannelException("Invalid value type " + type);
-    }
-    return types[type];
-  }
-
-  protected static void writeJavaObject(DataOutputStream stream,
-      JavaObjectRef value) throws IOException {
-    stream.writeByte(ValueType.JAVA_OBJECT.getTag());
-    stream.writeInt(value.getRefid());
-  }
-
-  protected static void writeJsObject(DataOutputStream stream,
-      JsObjectRef value) throws IOException {
-    stream.writeByte(ValueType.JS_OBJECT.getTag());
-    stream.writeInt(value.getRefid());
-  }
-
-  protected static void writeNull(DataOutputStream stream) throws IOException {
-    stream.writeByte(ValueType.NULL.getTag());
-  }
-
-  protected static void writeTaggedBoolean(DataOutputStream stream,
-      boolean value) throws IOException {
-    stream.writeByte(ValueType.BOOLEAN.getTag());
-    stream.writeBoolean(value);
-  }
-
-  protected static void writeTaggedByte(DataOutputStream stream, byte value)
-      throws IOException {
-    stream.writeByte(ValueType.BYTE.getTag());
-    stream.writeByte(value);
-  }
-
-  protected static void writeTaggedChar(DataOutputStream stream, char value)
-      throws IOException {
-    stream.writeByte(ValueType.CHAR.getTag());
-    stream.writeChar(value);
-  }
-
-  protected static void writeTaggedDouble(DataOutputStream stream, double value)
-      throws IOException {
-    stream.writeByte(ValueType.DOUBLE.getTag());
-    stream.writeDouble(value);
-  }
-
-  protected static void writeTaggedFloat(DataOutputStream stream, float value)
-      throws IOException {
-    stream.writeByte(ValueType.FLOAT.getTag());
-    stream.writeFloat(value);
-  }
-
-  protected static void writeTaggedInt(DataOutputStream stream, int value)
-      throws IOException {
-    stream.writeByte(ValueType.INT.getTag());
-    stream.writeInt(value);
-  }
-
-  protected static void writeTaggedShort(DataOutputStream stream, short value)
-      throws IOException {
-    stream.writeByte(ValueType.SHORT.getTag());
-    stream.writeShort(value);
-  }
-
-  protected static void writeTaggedString(DataOutputStream stream, String data)
-      throws IOException {
-    stream.writeByte(ValueType.STRING.getTag());
-    writeUtf8String(stream, data);
-  }
-
-  protected static void writeUtf8String(DataOutputStream stream, String data)
-      throws IOException {
-    try {
-      final byte[] bytes = data.getBytes("UTF8");
-      stream.writeInt(bytes.length);
-      stream.write(bytes);
-    } catch (UnsupportedEncodingException e) {
-      // TODO: Add description.
-      throw new RuntimeException();
-    }
-  }
-
-  private static void writeUndefined(DataOutputStream stream)
-      throws IOException {
-    stream.writeByte(ValueType.UNDEFINED.getTag());
-  }
-
-  private final ObjectRefFactory objectRefFactory;
-
-  private Socket socket;
-
-  private final DataInputStream streamFromOtherSide;
-
-  private final DataOutputStream streamToOtherSide;
-
-  public BrowserChannelPatched(Socket socket, ObjectRefFactory objectRefFactory)
-      throws IOException {
-    this(new BufferedInputStream(socket.getInputStream()),
-        new BufferedOutputStream(socket.getOutputStream()),
-        objectRefFactory);
-    this.socket = socket;
-  }
-
-  protected BrowserChannelPatched(InputStream inputStream, OutputStream outputStream,
-      ObjectRefFactory objectRefFactory) {
-    streamFromOtherSide = new DataInputStream(inputStream);
-    streamToOtherSide = new DataOutputStream(outputStream);
-    socket = null;
-    this.objectRefFactory = objectRefFactory;
-  }
-
-  public void endSession() {
-    Utility.close(streamFromOtherSide);
-    Utility.close(streamToOtherSide);
-    Utility.close(socket);
-  }
-
-  /**
-   * @return a set of remote object reference IDs to be freed.
-   */
-  public Set<Integer> getRefIdsForCleanup() {
-    return objectRefFactory.getRefIdsForCleanup();
-  }
-
-  public String getRemoteEndpoint() {
-    if (socket == null) {
-      return "";
-    }
-    return socket.getInetAddress().getCanonicalHostName() + ":"
-        + socket.getPort();
-  }
-
-  protected DataInputStream getStreamFromOtherSide() {
-    return streamFromOtherSide;
-  }
-
-  protected DataOutputStream getStreamToOtherSide() {
-    return streamToOtherSide;
-  }
-
-  protected Value readValue(DataInputStream stream) throws IOException {
-    ValueType tag;
-    try {
-      tag = readValueType(stream);
-    } catch (BrowserChannelException e) {
-      IOException ee = new IOException();
-      ee.initCause(e);
-      throw ee;
-    }
-    Value value = new Value();
-    switch (tag) {
-      case NULL:
-        value.setNull();
-        break;
-      case UNDEFINED:
-        value.setUndefined();
-        break;
-      case BOOLEAN:
-        value.setBoolean(stream.readByte() != 0);
-        break;
-      case BYTE:
-        value.setByte(stream.readByte());
-        break;
-      case CHAR:
-        value.setChar(stream.readChar());
-        break;
-      case FLOAT:
-        value.setFloat(stream.readFloat());
-        break;
-      case INT:
-        value.setInt(stream.readInt());
-        break;
-      case LONG:
-        value.setLong(stream.readLong());
-        break;
-      case DOUBLE:
-        value.setDouble(stream.readDouble());
-        break;
-      case SHORT:
-        value.setShort(stream.readShort());
-        break;
-      case STRING:
-        value.setString(readUtf8String(stream));
-        break;
-      case JS_OBJECT:
-        value.setJsObject(objectRefFactory.getJsObjectRef(stream.readInt()));
-        break;
-      case JAVA_OBJECT:
-        value.setJavaObject(objectRefFactory.getJavaObjectRef(
-            stream.readInt()));
-        break;
-    }
-    return value;
-  }
-
-  protected void sendFreedValues() throws IOException {
-    Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
-    int n = freed.size();
-    if (n > 0) {
-      int[] ids = new int[n];
-      int i = 0;
-      for (Integer id : freed) {
-        ids[i++] = id;
-      }
-      FreeMessage.send(this, ids);
-    }
-  }
-
-  protected void writeValue(DataOutputStream stream, Value value)
-      throws IOException {
-    if (value.isNull()) {
-      writeNull(stream);
-    } else if (value.isUndefined()) {
-      writeUndefined(stream);
-    } else if (value.isJsObject()) {
-      writeJsObject(stream, value.getJsObject());
-    } else if (value.isJavaObject()) {
-      writeJavaObject(stream, value.getJavaObject());
-    } else if (value.isBoolean()) {
-      writeTaggedBoolean(stream, value.getBoolean());
-    } else if (value.isByte()) {
-      writeTaggedByte(stream, value.getByte());
-    } else if (value.isChar()) {
-      writeTaggedChar(stream, value.getChar());
-    } else if (value.isShort()) {
-      writeTaggedShort(stream, value.getShort());
-    } else if (value.isDouble()) {
-      writeTaggedDouble(stream, value.getDouble());
-    } else if (value.isFloat()) {
-      writeTaggedFloat(stream, value.getFloat());
-    } else if (value.isInt()) {
-      writeTaggedInt(stream, value.getInt());
-    } else if (value.isString()) {
-      writeTaggedString(stream, value.getString());
-    } else {
-      assert false;
-    }
-  }
-}
diff --git a/gwtquery-core/src/test/java/com/google/gwt/junit/RunStyleHtmlUnitPatched.java b/gwtquery-core/src/test/java/com/google/gwt/junit/RunStyleHtmlUnitPatched.java
deleted file mode 100644 (file)
index c764486..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright 2009 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.junit;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.shell.HostedModePluginObject;
-import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
-
-import com.gargoylesoftware.htmlunit.AlertHandler;
-import com.gargoylesoftware.htmlunit.BrowserVersion;
-import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
-import com.gargoylesoftware.htmlunit.IncorrectnessListener;
-import com.gargoylesoftware.htmlunit.OnbeforeunloadHandler;
-import com.gargoylesoftware.htmlunit.Page;
-import com.gargoylesoftware.htmlunit.ScriptException;
-import com.gargoylesoftware.htmlunit.WebClient;
-import com.gargoylesoftware.htmlunit.WebWindow;
-import com.gargoylesoftware.htmlunit.html.HtmlPage;
-import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
-import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
-import com.gargoylesoftware.htmlunit.javascript.host.Window;
-
-import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject;
-
-import org.w3c.css.sac.CSSParseException;
-import org.w3c.css.sac.ErrorHandler;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Launches a web-mode test via HTMLUnit.
- */
-public class RunStyleHtmlUnitPatched extends RunStyle {
-
-  /**
-   * Runs HTMLUnit in a separate thread.
-   */
-  protected static class HtmlUnitThread extends Thread implements AlertHandler,
-      IncorrectnessListener, OnbeforeunloadHandler {
-
-    private final BrowserVersion browser;
-    private final boolean developmentMode;
-    private final TreeLogger treeLogger;
-    private final String url;
-    private Object waitForUnload = new Object();
-
-    public HtmlUnitThread(BrowserVersion browser, String url,
-        TreeLogger treeLogger, boolean developmentMode) {
-      this.browser = browser;
-      this.url = url;
-      this.treeLogger = treeLogger;
-      this.setName("htmlUnit client thread");
-      this.developmentMode = developmentMode;
-    }
-
-    public void handleAlert(Page page, String message) {
-      treeLogger.log(TreeLogger.ERROR, "Alert: " + message);
-    }
-
-    public boolean handleEvent(Page page, String returnValue) {
-      synchronized (waitForUnload) {
-        waitForUnload.notifyAll();
-      }
-      return true;
-    }
-
-    public void notify(String message, Object origin) {
-      if ("Obsolete content type encountered: 'text/javascript'.".equals(message)) {
-        // silently eat warning about text/javascript MIME type
-        return;
-      }
-      treeLogger.log(TreeLogger.WARN, message);
-    }
-
-    @Override
-    public void run() {
-      WebClient webClient = new WebClient(browser);
-      webClient.setAlertHandler(this);
-      // Adding a handler that ignores errors to work-around
-      // https://sourceforge.net/tracker/?func=detail&aid=3090806&group_id=47038&atid=448266
-      webClient.setCssErrorHandler(new ErrorHandler() {
-
-        public void error(CSSParseException exception) {
-          // ignore
-        }
-
-        public void fatalError(CSSParseException exception) {
-          treeLogger.log(TreeLogger.WARN,
-              "CSS fatal error: " + exception.getURI() + " ["
-                  + exception.getLineNumber() + ":"
-                  + exception.getColumnNumber() + "] " + exception.getMessage());
-        }
-
-        public void warning(CSSParseException exception) {
-          // ignore
-        }
-      });
-      webClient.setIncorrectnessListener(this);
-      webClient.setOnbeforeunloadHandler(this);
-      webClient.setJavaScriptErrorListener(new JavaScriptErrorListener() {
-
-        @Override
-        public void loadScriptError(HtmlPage htmlPage, URL scriptUrl,
-            Exception exception) {
-            treeLogger.log(TreeLogger.ERROR,
-              "Load Script Error: " + exception, exception);
-        }
-
-        @Override
-        public void malformedScriptURL(HtmlPage htmlPage, String url,
-            MalformedURLException malformedURLException) {
-          treeLogger.log(TreeLogger.ERROR,
-              "Malformed Script URL: " + malformedURLException.getLocalizedMessage());
-        }
-
-        @Override
-        public void scriptException(HtmlPage htmlPage,
-            ScriptException scriptException) {
-          treeLogger.log(TreeLogger.DEBUG,
-              "Script Exception: " + scriptException.getLocalizedMessage() +
-               ", line " + scriptException.getFailingLine());
-        }
-
-        @Override
-        public void timeoutError(HtmlPage htmlPage, long allowedTime,
-            long executionTime) {
-          treeLogger.log(TreeLogger.ERROR,
-              "Script Timeout Error " + executionTime + " > " + allowedTime);
-        }
-      });
-      setupWebClient(webClient);
-      try {
-        Page page = webClient.getPage(url);
-        webClient.waitForBackgroundJavaScriptStartingBefore(2000);
-        if (treeLogger.isLoggable(TreeLogger.SPAM)) {
-          treeLogger.log(TreeLogger.SPAM, "getPage returned "
-              + ((HtmlPage) page).asXml());
-        }
-        // TODO(amitmanjhi): call webClient.closeAllWindows()
-      } catch (FailingHttpStatusCodeException e) {
-        treeLogger.log(TreeLogger.ERROR, "HTTP request failed", e);
-        return;
-      } catch (MalformedURLException e) {
-        treeLogger.log(TreeLogger.ERROR, "Bad URL", e);
-        return;
-      } catch (IOException e) {
-        treeLogger.log(TreeLogger.ERROR, "I/O error on HTTP request", e);
-        return;
-      }
-    }
-
-    protected void setupWebClient(WebClient webClient) {
-      if (developmentMode) {
-        JavaScriptEngine hostedEngine = new HostedJavaScriptEngine(webClient,
-            treeLogger);
-        webClient.setJavaScriptEngine(hostedEngine);
-      }
-    }
-  }
-
-  /**
-   * JavaScriptEngine subclass that provides a hook of initializing the
-   * __gwt_HostedModePlugin property on any new window, so it acts just like
-   * Firefox with the XPCOM plugin installed.
-   */
-  private static class HostedJavaScriptEngine extends JavaScriptEngine {
-
-    private static final long serialVersionUID = 3594816610842448691L;
-    private final TreeLogger logger;
-
-    public HostedJavaScriptEngine(WebClient webClient, TreeLogger logger) {
-      super(webClient);
-      this.logger = logger;
-    }
-
-    @Override
-    public void initialize(WebWindow webWindow) {
-      // Hook in the hosted-mode plugin after initializing the JS engine.
-      super.initialize(webWindow);
-      Window window = (Window) webWindow.getScriptObject();
-      window.defineProperty("__gwt_HostedModePlugin",
-          new HostedModePluginObject(this, logger), ScriptableObject.READONLY);
-    }
-  }
-
-  private static final Map<String, BrowserVersion> BROWSER_MAP = createBrowserMap();
-
-  /*
-   * as long as this number is greater than 1, GWTTestCaseTest::testRetry will
-   * pass
-   */
-  private static final int DEFAULT_TRIES = 1;
-
-  private static final Set<Platform> PLATFORMS = ImmutableSet.of(Platform.HtmlUnitBug,
-      Platform.HtmlUnitLayout, Platform.HtmlUnitUnknown);
-
-  /**
-   * Returns the list of browsers Htmlunit emulates as a comma separated string.
-   */
-  static String getBrowserList() {
-    StringBuffer sb = new StringBuffer();
-    for (String str : BROWSER_MAP.keySet()) {
-      sb.append(str);
-      sb.append(",");
-    }
-    if (sb.length() > 1) {
-      return sb.substring(0, sb.length() - 1);
-    }
-    return sb.toString();
-  }
-
-  private static Map<String, BrowserVersion> createBrowserMap() {
-    Map<String, BrowserVersion> browserMap = new HashMap<String, BrowserVersion>();
-    for (BrowserVersion browser : new BrowserVersion[] {
-        BrowserVersion.FIREFOX_3_6, BrowserVersion.INTERNET_EXPLORER_6,
-        BrowserVersion.INTERNET_EXPLORER_7}) {
-      browserMap.put(browser.getNickname(), browser);
-    }
-    return Collections.unmodifiableMap(browserMap);
-  }
-
-  private Set<BrowserVersion> browsers = new HashSet<BrowserVersion>();
-  private boolean developmentMode;
-  private final List<Thread> threads = new ArrayList<Thread>();
-
-  /**
-   * Create a RunStyle instance with the passed-in browser targets.
-   */
-  public RunStyleHtmlUnitPatched(JUnitShell shell) {
-    super(shell);
-  }
-
-  @Override
-  public Set<Platform> getPlatforms() {
-    return PLATFORMS;
-  }
-
-  @Override
-  public int initialize(String args) {
-    if (args == null || args.length() == 0) {
-      // If no browsers specified, default to Firefox 3.
-      args = "FF3.6";
-    }
-    Set<BrowserVersion> browserSet = new HashSet<BrowserVersion>();
-    for (String browserName : args.split(",")) {
-      BrowserVersion browser = BROWSER_MAP.get(browserName);
-      if (browser == null) {
-        getLogger().log(
-            TreeLogger.ERROR,
-            "RunStyleHtmlUnit: Unknown browser " + "name " + browserName
-                + ", expected browser name: one of " + BROWSER_MAP.keySet());
-        return -1;
-      }
-      browserSet.add(browser);
-    }
-    browsers = Collections.unmodifiableSet(browserSet);
-
-    setTries(DEFAULT_TRIES); // set to the default value for this RunStyle
-    return browsers.size();
-  }
-
-  @Override
-  public void launchModule(String moduleName) {
-    for (BrowserVersion browser : browsers) {
-      String url = shell.getModuleUrl(moduleName);
-      HtmlUnitThread hut = createHtmlUnitThread(browser, url);
-      TreeLogger logger = shell.getTopLogger();
-      if (logger.isLoggable(TreeLogger.INFO)) {
-        logger.log(TreeLogger.INFO,
-            "Starting " + url + " on browser " + browser.getNickname());
-      }
-      /*
-       * TODO (amitmanjhi): Is it worth pausing here and waiting for the main
-       * test thread to get to an "okay" state.
-       */
-      hut.start();
-      threads.add(hut);
-    }
-  }
-
-  public int numBrowsers() {
-    return browsers.size();
-  }
-
-  @Override
-  public boolean setupMode(TreeLogger logger, boolean developmentMode) {
-    this.developmentMode = developmentMode;
-    return true;
-  }
-
-  protected HtmlUnitThread createHtmlUnitThread(BrowserVersion browser,
-      String url) {
-    return new HtmlUnitThread(browser, url, shell.getTopLogger().branch(
-        TreeLogger.SPAM, "logging for HtmlUnit thread"), developmentMode);
-  }
-}
index e94d27eba7089910f145adb1601a1eb9c80641d2..0bda7e76f601eb290a31aeb18ba7213ca5d5bd6e 100644 (file)
@@ -3,7 +3,9 @@ package com.google.gwt.query.client;
 import junit.framework.Test;
 
 import com.google.gwt.junit.tools.GWTTestSuite;
+import com.google.gwt.query.client.ajax.AjaxTestJre;
 import com.google.gwt.query.client.ajax.AjaxTestGwt;
+import com.google.gwt.query.client.dbinding.DataBindingTestJre;
 import com.google.gwt.query.client.dbinding.DataBindingTestGwt;
 import com.google.gwt.query.client.deferred.DeferredTestGwt;
 import com.google.gwt.query.client.impl.SelectorEnginesTestGwt;
@@ -15,6 +17,8 @@ import com.google.gwt.query.client.impl.SelectorEnginesTestGwt;
 public class GQueryGwtSuiteTest extends GWTTestSuite {
   public static Test suite() {
       GWTTestSuite suite = new GWTTestSuite( "GQuery Suite" );
+      suite.addTestSuite(AjaxTestJre.class);
+      suite.addTestSuite(DataBindingTestJre.class);
       suite.addTestSuite(DataBindingTestGwt.class);
       suite.addTestSuite(GQueryAjaxTestGwt.class);
       suite.addTestSuite(AjaxTestGwt.class);
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxCommon.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxCommon.java
deleted file mode 100644 (file)
index 9c03b82..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2013, The gwtquery team.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.query.client.ajax;
-
-import com.google.gwt.http.client.Response;
-import com.google.gwt.junit.DoNotRunWith;
-import com.google.gwt.junit.Platform;
-import com.google.gwt.junit.client.GWTTestCase;
-import com.google.gwt.query.client.Binder;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQ;
-import com.google.gwt.query.client.Promise;
-import com.google.gwt.query.client.plugins.ajax.Ajax;
-import com.google.gwt.query.client.plugins.ajax.Ajax.Settings;
-
-/**
- * Common Tests for Data Binding and Ajax which can run either in JVM and GWT
- */
-public abstract class AjaxCommon extends GWTTestCase {
-
-  protected String echoUrl, echoUrlCORS;
-  protected Binder json, jsonGET;
-  protected String servletPath = "test.json";
-  
-  private Function failFunction = new Function() {
-    public void f() {
-      fail();
-    }
-  };
-  
-  private Function finishFunction = new Function() {
-    public void f() {
-      finishTest();
-    }
-  };
-  
-  public AjaxCommon() {
-    jsonGET = GQ.create("data: {a: abc, d: def}");
-    json = GQ.create("a: abc, d: def");
-  }
-  
-  private Promise performAjaxJsonTest(Settings s) {
-    delayTestFinish(5000);
-    return Ajax.ajax(s)
-      .done(new Function(){public void f() {
-        Binder p = arguments(0);
-        assertEquals("abc", p.get("a"));
-        finishTest();
-      }})
-      .fail(failFunction);
-  }
-  
-  private Promise performAjaxJsonTest_CORS(Settings s) {
-    return performAjaxJsonTest(s)
-      .done(new Function() {public void f() {
-        Response r = arguments(3);
-        assertNotNull(r.getHeader("Access-Control-Allow-Origin"));
-        assertTrue(r.getHeader("Access-Control-Allow-Origin").contains(GQ.domain));
-      }});
-  }
-
-  public void testAjaxJsonPost() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      .setUrl(echoUrl)
-      .setData(json)
-      .setDataType("json")
-      .setUsername("testuser")
-      .setPassword("testpassword");
-
-    performAjaxJsonTest(s);
-  }
-
-  // This test needs htmlunit at least 2.11
-  // https://groups.google.com/forum/#!msg/google-web-toolkit/dmyTt1Bh0pM/lBTIFiTyrpkJ
-  //
-  // It is necessary to patch RunStyleHtmlUnit because GWT default browser is FF3 since
-  // minimun version in htmlunit-2.1x is FF3.6
-  // It is necessary to patch BrowserChannel as well because convertFromJavaValue receives
-  // non string objects under certain circumstances.
-  @DoNotRunWith(Platform.HtmlUnitBug)
-  public void testAjaxJsonPost_CORS() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      .setUrl(echoUrlCORS)
-      .setData(json)
-      .setDataType("json");
-    
-    performAjaxJsonTest_CORS(s);
-  }
-  
-  public void testAjaxJsonGet() {
-    Settings s = Ajax.createSettings()
-      .setType("get")
-      .setUrl(echoUrl)
-      .setData(jsonGET)
-      .setDataType("json");
-
-    performAjaxJsonTest(s);
-  }
-  
-  @DoNotRunWith(Platform.HtmlUnitBug)
-  public void testAjaxJsonGet_CORS() {
-    Settings s = Ajax.createSettings()
-      .setType("get")
-      .setUrl(echoUrlCORS)
-      .setData(jsonGET)
-      .setDataType("json");
-
-    performAjaxJsonTest_CORS(s);
-  }
-  
-  public void testAjaxGetJsonP() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      .setType("post")
-      .setUrl(echoUrlCORS)
-      .setData(jsonGET)
-      .setDataType("jsonp");
-
-    performAjaxJsonTest(s);
-  }
-  
-  public void testJsonValidService() {
-    delayTestFinish(5000);
-    // Use a public json service supporting callback parameter
-    Ajax.getJSONP("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?callback=?&key=NO-KEY")
-      .done(new Function(){
-        public void f() {
-          Binder p = arguments(0);
-          // It should return error since we do not use a valid key
-          // {"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
-          assertEquals(400, p.<Binder>get("error").<Number>get("code").intValue());
-          finishTest();
-        }
-      })
-      .fail(failFunction);
-  }
-  
-  public void testInvalidOrigin() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      // Use a public json service non CORS enabled
-      .setUrl("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?key=NO-KEY")
-      .setDataType("json")
-      .setTimeout(1000);
-    
-    Ajax.ajax(s)
-      .done(failFunction)
-      .fail(finishFunction);
-  }
-  
-  public void testJsonInvalidService() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      // Use a valid javascript which does not wrap content in a callback
-      .setUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js")
-      .setDataType("jsonp")
-      .setTimeout(1000);
-    
-    Ajax.ajax(s)
-      .done(failFunction)
-      .fail(finishFunction);
-  }
-  
-  // For some reason htmlunit 2.16 does not raises a timeout, 2.9 does though, 
-  // when server sleeps or connection lasts a while. Tested with htmlunit 2.16
-  //  @DoNotRunWith(Platform.HtmlUnitBug)
-  public void testAjaxTimeout() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      .setTimeout(100)
-      .setType("get")
-      // Connecting to private networks out of our LAN raises a timeout because
-      // there is no route for them in public networks.  
-      .setUrl("http://10.32.45.67:7654");
-
-    Ajax.ajax(s)
-      .done(failFunction)
-      .fail(finishFunction);
-  }
-  
-  public void testJsonpTimeout() {
-    delayTestFinish(5000);
-    Settings s = Ajax.createSettings()
-      .setTimeout(1000)
-      .setDataType("jsonp")
-      .setUrl(echoUrl + "?timeout=2000");
-
-    Ajax.ajax(s)
-      .done(failFunction)
-      .fail(finishFunction);     
-  }
-  
-  public void testAjaxError() {
-    delayTestFinish(5000);
-    String url = "http://127.0.0.1/nopage";
-
-    Ajax.ajax(Ajax.createSettings().setTimeout(1000).setUrl(url))
-      .done(new Function(){
-        public void f() {
-          fail();
-        }
-      }).fail(new Function(){
-        public void f() {
-          finishTest();
-        }
-      });
-  }
-  
-  public void testLoadScript() {
-    delayTestFinish(5000);
-    String url = "http://code.jquery.com/jquery-2.0.3.min.js";
-    Ajax.loadScript(url)
-      .done(new Function(){
-        public void f() {
-          finishTest();
-        }
-      }).fail(new Function(){
-        public void f() {
-          fail();
-        }
-      });
-  }
-
-  public void testGetScriptFail() {
-    delayTestFinish(5000);
-    String url = "http://127.0.0.1/nopage";
-    Ajax.getScript(url)
-      .done(new Function(){
-        public void f() {
-          fail();
-        }
-      }).fail(new Function(){
-        public void f() {
-          finishTest();
-        }
-      });
-  }  
-}
\ No newline at end of file
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTest.java
deleted file mode 100644 (file)
index 031e530..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2013, The gwtquery team.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.query.client.ajax;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-import javax.servlet.Servlet;
-
-import org.mortbay.jetty.Server;
-import org.mortbay.jetty.handler.HandlerWrapper;
-import org.mortbay.jetty.servlet.DefaultServlet;
-import org.mortbay.jetty.webapp.WebAppClassLoader;
-import org.mortbay.jetty.webapp.WebAppContext;
-
-import com.google.gwt.query.servlet.GQAjaxTestServlet;
-
-/**
- * Tests for Data Binders and Ajax run in the JVM
- */
-public class AjaxTest extends AjaxCommon {
-  
-  static Server server;
-  static int port = new Random().nextInt(1000) + 2000;
-
-  public String getModuleName() {
-    return null;
-  }
-  
-  public AjaxTest() throws Exception {
-    echoUrl = "http://127.0.0.1:" + port + "/" + servletPath;
-    echoUrlCORS = "http://localhost:" + port + "/" + servletPath + "?cors=true";
-    startWebServer(port);
-  }
-  
-  protected void startWebServer(int port) throws Exception {
-    if (server == null) {
-      final Map<String, Class<? extends Servlet>> servlets = new HashMap<String, Class<? extends Servlet>>();
-      servlets.put("/" + servletPath, GQAjaxTestServlet.class);
-      server = createWebServer(port, ".", null, servlets, null);
-    }
-  }
-
-  public static Server createWebServer(final int port, final String resourceBase, final String[] classpath,
-      final Map<String, Class<? extends Servlet>> servlets, final HandlerWrapper handler) throws Exception {
-    
-    final Server server = new Server(port);
-
-    final WebAppContext context = new WebAppContext();
-    context.setContextPath("/");
-    context.setResourceBase(resourceBase);
-
-    if (servlets != null) {
-      for (final Map.Entry<String, Class<? extends Servlet>> entry : servlets.entrySet()) {
-        final String pathSpec = entry.getKey();
-        final Class<? extends Servlet> servlet = entry.getValue();
-        context.addServlet(servlet, pathSpec);
-
-        // disable defaults if someone likes to register his own root servlet
-        if ("/".equals(pathSpec)) {
-          context.setDefaultsDescriptor(null);
-          context.addServlet(DefaultServlet.class, "/favicon.ico");
-        }
-      }
-    }
-
-    final WebAppClassLoader loader = new WebAppClassLoader(context);
-    if (classpath != null) {
-      for (final String path : classpath) {
-        loader.addClassPath(path);
-      }
-    }
-    context.setClassLoader(loader);
-    if (handler != null) {
-      handler.setHandler(context);
-      server.setHandler(handler);
-    } else {
-      server.setHandler(context);
-    }
-    server.start();
-    return server;
-  }
-
-}
\ No newline at end of file
index 0e6bf736ba4371378018667ea8a4e0566a81d411..b69c0ac594131d37d02b40b9c62e2063f7aa787b 100644 (file)
@@ -21,7 +21,7 @@ import com.google.gwt.core.client.GWT;
 /**
  * Test for data binding and Ajax which is run in gwt
  */
-public class AjaxTestGwt extends AjaxCommon {
+public class AjaxTestGwt extends AjaxTests {
 
   @Override
   public String getModuleName() {
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTestJre.java
new file mode 100644 (file)
index 0000000..abe00e3
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013, The gwtquery team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.ajax;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import javax.servlet.Servlet;
+
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.HandlerWrapper;
+import org.mortbay.jetty.servlet.DefaultServlet;
+import org.mortbay.jetty.webapp.WebAppClassLoader;
+import org.mortbay.jetty.webapp.WebAppContext;
+
+import com.google.gwt.query.servlet.GQAjaxTestServlet;
+import com.google.gwt.query.vm.AjaxTransportJre;
+
+/**
+ * Tests for Data Binders and Ajax run in the JVM
+ */
+public class AjaxTestJre extends AjaxTests {
+  
+  static Server server;
+  static int port = new Random().nextInt(1000) + 2000;
+
+  public String getModuleName() {
+    return null;
+  }
+  
+  public AjaxTestJre() throws Exception {
+    String localDomain = "http://127.0.0.1:" + port;
+    AjaxTransportJre.enableCORS(localDomain);
+    String corsDomain = "http://localhost:" + port;
+    
+    echoUrl = localDomain + "/" + servletPath;
+    echoUrlCORS = corsDomain + "/" + servletPath + "?cors=true";
+    startWebServer(port);
+  }
+  
+  protected void startWebServer(int port) throws Exception {
+    if (server == null) {
+      final Map<String, Class<? extends Servlet>> servlets = new HashMap<String, Class<? extends Servlet>>();
+      servlets.put("/" + servletPath, GQAjaxTestServlet.class);
+      server = createWebServer(port, ".", null, servlets, null);
+    }
+  }
+
+  public static Server createWebServer(final int port, final String resourceBase, final String[] classpath,
+      final Map<String, Class<? extends Servlet>> servlets, final HandlerWrapper handler) throws Exception {
+    
+    final Server server = new Server(port);
+
+    final WebAppContext context = new WebAppContext();
+    context.setContextPath("/");
+    context.setResourceBase(resourceBase);
+
+    if (servlets != null) {
+      for (final Map.Entry<String, Class<? extends Servlet>> entry : servlets.entrySet()) {
+        final String pathSpec = entry.getKey();
+        final Class<? extends Servlet> servlet = entry.getValue();
+        context.addServlet(servlet, pathSpec);
+
+        // disable defaults if someone likes to register his own root servlet
+        if ("/".equals(pathSpec)) {
+          context.setDefaultsDescriptor(null);
+          context.addServlet(DefaultServlet.class, "/favicon.ico");
+        }
+      }
+    }
+
+    final WebAppClassLoader loader = new WebAppClassLoader(context);
+    if (classpath != null) {
+      for (final String path : classpath) {
+        loader.addClassPath(path);
+      }
+    }
+    context.setClassLoader(loader);
+    if (handler != null) {
+      handler.setHandler(context);
+      server.setHandler(handler);
+    } else {
+      server.setHandler(context);
+    }
+    server.start();
+    return server;
+  }
+
+}
\ No newline at end of file
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/ajax/AjaxTests.java
new file mode 100644 (file)
index 0000000..f6a064c
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2013, The gwtquery team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.ajax;
+
+import com.google.gwt.http.client.Response;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.query.client.Binder;
+import com.google.gwt.query.client.Function;
+import com.google.gwt.query.client.GQ;
+import com.google.gwt.query.client.Promise;
+import com.google.gwt.query.client.plugins.ajax.Ajax;
+import com.google.gwt.query.client.plugins.ajax.Ajax.Settings;
+
+/**
+ * Common Tests for Data Binding and Ajax which can run either in JVM and GWT
+ */
+public abstract class AjaxTests extends GWTTestCase {
+
+  protected String echoUrl, echoUrlCORS;
+  protected Binder json, jsonGET;
+  protected String servletPath = "test.json";
+  
+  private Function failFunction = new Function() {
+    public void f() {
+      fail();
+    }
+  };
+  
+  private Function finishFunction = new Function() {
+    public void f() {
+      finishTest();
+    }
+  };
+  
+  public AjaxTests() {
+    jsonGET = GQ.create("data: {a: abc, d: def}");
+    json = GQ.create("a: abc, d: def");
+  }
+  
+  private Promise performAjaxJsonTest(Settings s) {
+    delayTestFinish(5000);
+    return Ajax.ajax(s)
+      .done(new Function(){public void f() {
+        Binder p = arguments(0);
+        assertEquals("abc", p.get("a"));
+        finishTest();
+      }})
+      .fail(failFunction);
+  }
+  
+  private Promise performAjaxJsonTest_CORS(Settings s) {
+    return performAjaxJsonTest(s)
+      .done(new Function() {public void f() {
+        Response r = arguments(3);
+        assertNotNull(r.getHeader("Access-Control-Allow-Origin"));
+      }});
+  }
+
+  public void testAjaxJsonPost() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      .setUrl(echoUrl)
+      .setData(json)
+      .setDataType("json")
+      .setUsername("testuser")
+      .setPassword("testpassword");
+
+    performAjaxJsonTest(s);
+  }
+
+  // This test needs htmlunit at least 2.11
+  // https://groups.google.com/forum/#!msg/google-web-toolkit/dmyTt1Bh0pM/lBTIFiTyrpkJ
+  //
+  // It is necessary to patch RunStyleHtmlUnit because GWT default browser is FF3 since
+  // minimun version in htmlunit-2.1x is FF3.6
+  // It is necessary to patch BrowserChannel as well because convertFromJavaValue receives
+  // non string objects under certain circumstances.
+  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testAjaxJsonPost_CORS() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      .setUrl(echoUrlCORS)
+      .setData(json)
+      .setDataType("json");
+    
+    performAjaxJsonTest_CORS(s);
+  }
+  
+  public void testAjaxJsonGet() {
+    Settings s = Ajax.createSettings()
+      .setType("get")
+      .setUrl(echoUrl)
+      .setData(jsonGET)
+      .setDataType("json");
+
+    performAjaxJsonTest(s);
+  }
+  
+  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testAjaxJsonGet_CORS() {
+    Settings s = Ajax.createSettings()
+      .setType("get")
+      .setUrl(echoUrlCORS)
+      .setData(jsonGET)
+      .setDataType("json");
+
+    performAjaxJsonTest_CORS(s);
+  }
+  
+  public void testAjaxGetJsonP() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      .setType("post")
+      .setUrl(echoUrlCORS)
+      .setData(jsonGET)
+      .setDataType("jsonp");
+
+    performAjaxJsonTest(s);
+  }
+  
+  public void testJsonValidService() {
+    delayTestFinish(5000);
+    // Use a public json service supporting callback parameter
+    Ajax.getJSONP("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?callback=?&key=NO-KEY")
+      .done(new Function(){
+        public void f() {
+          Binder p = arguments(0);
+          // It should return error since we do not use a valid key
+          // {"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
+          assertEquals(400, p.<Binder>get("error").<Number>get("code").intValue());
+          finishTest();
+        }
+      })
+      .fail(failFunction);
+  }
+  
+  public void testInvalidOrigin() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      // Use a public json service non CORS enabled
+      .setUrl("https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?key=NO-KEY")
+      .setDataType("json")
+      .setTimeout(1000);
+    
+    Ajax.ajax(s)
+      .done(failFunction)
+      .fail(finishFunction);
+  }
+  
+  public void testJsonInvalidService() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      // Use a valid javascript which does not wrap content in a callback
+      .setUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js")
+      .setDataType("jsonp")
+      .setTimeout(1000);
+    
+    Ajax.ajax(s)
+      .done(failFunction)
+      .fail(finishFunction);
+  }
+  
+  // For some reason htmlunit 2.16 does not raises a timeout, 2.9 does though, 
+  // when server sleeps or connection lasts a while. Tested with htmlunit 2.16
+  //  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testAjaxTimeout() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      .setTimeout(100)
+      .setType("get")
+      // Connecting to private networks out of our LAN raises a timeout because
+      // there is no route for them in public networks.  
+      .setUrl("http://10.32.45.67:7654");
+
+    Ajax.ajax(s)
+      .done(failFunction)
+      .fail(finishFunction);
+  }
+  
+  public void testJsonpTimeout() {
+    delayTestFinish(5000);
+    Settings s = Ajax.createSettings()
+      .setTimeout(1000)
+      .setDataType("jsonp")
+      .setUrl(echoUrl + "?timeout=2000");
+
+    Ajax.ajax(s)
+      .done(failFunction)
+      .fail(finishFunction);     
+  }
+  
+  public void testAjaxError() {
+    delayTestFinish(5000);
+    String url = "http://127.0.0.1/nopage";
+
+    Ajax.ajax(Ajax.createSettings().setTimeout(1000).setUrl(url))
+      .done(new Function(){
+        public void f() {
+          fail();
+        }
+      }).fail(new Function(){
+        public void f() {
+          finishTest();
+        }
+      });
+  }
+  
+  public void testLoadScript() {
+    delayTestFinish(5000);
+    String url = "http://code.jquery.com/jquery-2.0.3.min.js";
+    Ajax.loadScript(url)
+      .done(new Function(){
+        public void f() {
+          finishTest();
+        }
+      }).fail(new Function(){
+        public void f() {
+          fail();
+        }
+      });
+  }
+
+  public void testGetScriptFail() {
+    delayTestFinish(5000);
+    String url = "http://127.0.0.1/nopage";
+    Ajax.getScript(url)
+      .done(new Function(){
+        public void f() {
+          fail();
+        }
+      }).fail(new Function(){
+        public void f() {
+          finishTest();
+        }
+      });
+  }  
+}
\ No newline at end of file
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java
deleted file mode 100644 (file)
index 04bae0b..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2013, The gwtquery team.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.query.client.dbinding;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-
-import com.google.gwt.junit.client.GWTTestCase;
-import com.google.gwt.query.client.Function;
-import com.google.gwt.query.client.GQ;
-import com.google.gwt.query.client.builders.JsonBuilder;
-import com.google.gwt.query.client.builders.Name;
-
-/**
- * Tests for Deferred which can run either in JVM and GWT
- */
-public class DataBindingTest extends GWTTestCase {
-
-  public String getModuleName() {
-    return null;
-  }
-
-  public interface Item extends JsonBuilder {
-    Date getDate();
-    void setDate(Date d);
-  }
-
-  public interface JsonExample extends JsonBuilder {
-    int getA();
-    JsonExample getB();
-    @Name("M")
-    int getM();
-    @Name("u")
-    String getUrl();
-    long getD();
-    Boolean getZ();
-    String[] getT();
-    JsonExample setT(String[] strings);
-    JsonExample setZ(Boolean b);
-    JsonExample setD(long l);
-    List<Item> getItems();
-    void setItems(List<Item> a);
-    String y();
-    void y(String s);
-    Function getF();
-    void setF(Function f);
-  }
-
-  boolean functionRun = false;
-  public void testJsonBuilder() {
-    String json = "{M:0, a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true, 'items':[{'date':100}]}";
-
-    JsonExample c = GQ.create(JsonExample.class);
-    assertEquals(0, c.getA());
-    c.parse(json, true);
-
-    assertEquals(0, c.getM());
-    assertEquals(1, c.getA());
-    assertNotNull(c.getB());
-    assertEquals(2, c.getB().getA());
-    assertEquals(3, c.getB().getB().getA());
-    assertTrue(c.getZ());
-    assertEquals("hola", c.getT()[0]);
-    assertEquals("adios", c.getT()[1]);
-    assertEquals("url", c.getUrl());
-    c.setT(new String[]{"foo", "bar"})
-     .setZ(false).setD(1234);
-    assertFalse(c.getZ());
-    assertEquals("foo", c.getT()[0]);
-    assertEquals("bar", c.getT()[1]);
-    assertEquals(1234l, c.getD());
-    c.y("y");
-    assertEquals("y", c.y());
-    assertEquals(1, c.getItems().size());
-
-    c.setF(new Function() {
-      public void f() {
-        functionRun = true;
-      }
-    });
-    assertFalse(functionRun);
-    c.getF().f();
-    assertTrue(functionRun);
-
-    Item i1 = GQ.create(Item.class);
-    Item i2 = GQ.create(Item.class);
-    i1.setDate(new Date(2000));
-    i2.setDate(new Date(3000));
-    Item[] items = new Item[]{i1, i2};
-    c.setItems(Arrays.asList(items));
-    assertEquals(2000l, c.getItems().get(0).getDate().getTime());
-    assertEquals(3000l, c.getItems().get(1).getDate().getTime());
-
-    assertFalse(c.toJson().startsWith("{\"jsonExample\":"));
-    assertTrue(c.toJsonWithName().startsWith("{\"jsonExample\":"));
-    assertTrue(c.toJson().contains("\"items\":[{\"date\":"));
-    assertTrue(c.toQueryString().contains("t[]=bar"));
-    assertTrue(c.toQueryString().contains("a=1"));
-    assertTrue(c.toQueryString().contains("\"a\":2"));
-    
-    assertEquals(1, c.<Number>get("a").intValue());
-  }
-}
\ No newline at end of file
index bcd697b1021548273cb3c2345bdfc338f1f16e35..3cd087ce6d271c88a0770713f81318c47a096813 100644 (file)
@@ -19,7 +19,7 @@ package com.google.gwt.query.client.dbinding;
 /**
  * Test for data binding shared code run in gwt
  */
-public class DataBindingTestGwt extends DataBindingTest {
+public class DataBindingTestGwt extends DataBindingTestJre {
 
   @Override
   public String getModuleName() {
diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTestJre.java
new file mode 100644 (file)
index 0000000..9fa9a55
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013, The gwtquery team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.dbinding;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.query.client.Function;
+import com.google.gwt.query.client.GQ;
+import com.google.gwt.query.client.builders.JsonBuilder;
+import com.google.gwt.query.client.builders.Name;
+
+/**
+ * Tests for Deferred which can run either in JVM and GWT
+ */
+public class DataBindingTestJre extends GWTTestCase {
+
+  public String getModuleName() {
+    return null;
+  }
+
+  public interface Item extends JsonBuilder {
+    Date getDate();
+    void setDate(Date d);
+  }
+
+  public interface JsonExample extends JsonBuilder {
+    int getA();
+    JsonExample getB();
+    @Name("M")
+    int getM();
+    @Name("u")
+    String getUrl();
+    long getD();
+    Boolean getZ();
+    String[] getT();
+    JsonExample setT(String[] strings);
+    JsonExample setZ(Boolean b);
+    JsonExample setD(long l);
+    List<Item> getItems();
+    void setItems(List<Item> a);
+    String y();
+    void y(String s);
+    Function getF();
+    void setF(Function f);
+  }
+
+  boolean functionRun = false;
+  public void testJsonBuilder() {
+    String json = "{M:0, a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true, 'items':[{'date':100}]}";
+
+    JsonExample c = GQ.create(JsonExample.class);
+    assertEquals(0, c.getA());
+    c.parse(json, true);
+
+    assertEquals(0, c.getM());
+    assertEquals(1, c.getA());
+    assertNotNull(c.getB());
+    assertEquals(2, c.getB().getA());
+    assertEquals(3, c.getB().getB().getA());
+    assertTrue(c.getZ());
+    assertEquals("hola", c.getT()[0]);
+    assertEquals("adios", c.getT()[1]);
+    assertEquals("url", c.getUrl());
+    c.setT(new String[]{"foo", "bar"})
+     .setZ(false).setD(1234);
+    assertFalse(c.getZ());
+    assertEquals("foo", c.getT()[0]);
+    assertEquals("bar", c.getT()[1]);
+    assertEquals(1234l, c.getD());
+    c.y("y");
+    assertEquals("y", c.y());
+    assertEquals(1, c.getItems().size());
+
+    c.setF(new Function() {
+      public void f() {
+        functionRun = true;
+      }
+    });
+    assertFalse(functionRun);
+    c.getF().f();
+    assertTrue(functionRun);
+
+    Item i1 = GQ.create(Item.class);
+    Item i2 = GQ.create(Item.class);
+    i1.setDate(new Date(2000));
+    i2.setDate(new Date(3000));
+    Item[] items = new Item[]{i1, i2};
+    c.setItems(Arrays.asList(items));
+    assertEquals(2000l, c.getItems().get(0).getDate().getTime());
+    assertEquals(3000l, c.getItems().get(1).getDate().getTime());
+
+    assertFalse(c.toJson().startsWith("{\"jsonExample\":"));
+    assertTrue(c.toJsonWithName().startsWith("{\"jsonExample\":"));
+    assertTrue(c.toJson().contains("\"items\":[{\"date\":"));
+    assertTrue(c.toQueryString().contains("t[]=bar"));
+    assertTrue(c.toQueryString().contains("a=1"));
+    assertTrue(c.toQueryString().contains("\"a\":2"));
+    
+    assertEquals(1, c.<Number>get("a").intValue());
+  }
+}
\ No newline at end of file