/* * 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.user.client.rpc.impl; import com.google.gwt.core.client.GwtScriptOnly; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsonUtils; import com.google.gwt.core.client.UnsafeNativeLong; import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; import com.google.gwt.user.client.rpc.SerializationException; /** * The web-mode only version of ClientSerializationStreamReader. Any changes to this class to deal * with protocol changes must also be applied to the devmode version of * ClientSerializationStreamReader. */ @GwtScriptOnly public final class ClientSerializationStreamReader extends AbstractSerializationStreamReader { private static native JavaScriptObject eval(String encoded) /*-{ return eval(encoded); }-*/; private static native int getLength(JavaScriptObject array) /*-{ return array.length; }-*/; int index; JavaScriptObject results; JavaScriptObject stringTable; private Serializer serializer; public ClientSerializationStreamReader(Serializer serializer) { this.serializer = serializer; } @Override public void prepareToRead(String encoded) throws SerializationException { /* * Need to read the version from the string since version is later set in * super.prepareToRead() from the evaluated payload but that is too late. */ if (readVersion(encoded) < SERIALIZATION_STREAM_JSON_VERSION) { // Versions prior to 8 uses almost JSON with Javascript is special cases; e.g., using ].concat([, // non-stringified NaN/Infinity or ''+'' concatenated strings. results = eval(encoded); } else { results = JsonUtils.safeEval(encoded); } index = getLength(results); super.prepareToRead(encoded); if (getVersion() < SERIALIZATION_STREAM_MIN_VERSION || getVersion() > SERIALIZATION_STREAM_MAX_VERSION) { throw new IncompatibleRemoteServiceException("Got version " + getVersion() + ", expected version between " + SERIALIZATION_STREAM_MIN_VERSION + " and " + SERIALIZATION_STREAM_MAX_VERSION); } if (!areFlagsValid()) { throw new IncompatibleRemoteServiceException("Got an unknown flag from " + "server: " + getFlags()); } stringTable = readJavaScriptObject(); } public native boolean readBoolean() /*-{ return !!this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; public native byte readByte() /*-{ return this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; public native char readChar() /*-{ return this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; public native double readDouble() /*-{ return Number(this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]); }-*/; public native float readFloat() /*-{ return Number(this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]); }-*/; public native int readInt() /*-{ return this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; @UnsafeNativeLong public native long readLong() /*-{ var s = this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; return @ClientSerializationStreamReader::longFromBase64(Ljava/lang/String;)(s); }-*/; public native short readShort() /*-{ return this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; public String readString() { return getString(readInt()); } @Override protected Object deserialize(String typeSignature) throws SerializationException { int id = reserveDecodedObjectIndex(); Object instance = serializer.instantiate(this, typeSignature); rememberDecodedObject(id, instance); serializer.deserialize(this, instance, typeSignature); return instance; } @Override protected native String getString(int index) /*-{ // index is 1-based return index > 0 ? this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::stringTable[index - 1] : null; }-*/; private native JavaScriptObject readJavaScriptObject() /*-{ return this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::results[--this.@com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader::index]; }-*/; private static int readVersion(String encodedString) { String versionStr = encodedString.substring(encodedString.lastIndexOf(",") + 1, encodedString.lastIndexOf("]")); return Integer.parseInt(versionStr.trim()); } }