PageRenderTime 30ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/gdevelop/gwt/syncrpc/SyncClientSerializationStreamReader.java

http://gwt-syncproxy.googlecode.com/
Java | 756 lines | 581 code | 102 blank | 73 comment | 69 complexity | ef6ca57a7511f59c7797ac2bdeee8269 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright www.gdevelop.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.gdevelop.gwt.syncrpc;
  17. import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
  18. import com.google.gwt.user.client.rpc.SerializationException;
  19. import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader;
  20. import com.google.gwt.user.server.rpc.SerializationPolicy;
  21. import com.google.gwt.user.server.rpc.impl.SerializabilityUtil;
  22. import com.google.gwt.user.server.rpc.impl.SerializedInstanceReference;
  23. import java.io.BufferedReader;
  24. import java.io.FileReader;
  25. import java.lang.reflect.Array;
  26. import java.lang.reflect.Constructor;
  27. import java.lang.reflect.Field;
  28. import java.lang.reflect.InvocationTargetException;
  29. import java.lang.reflect.Method;
  30. import java.lang.reflect.Modifier;
  31. import java.util.ArrayList;
  32. import java.util.IdentityHashMap;
  33. import java.util.LinkedList;
  34. import java.util.List;
  35. import java.util.Map;
  36. /**
  37. * @see com.google.gwt.user.client.rpc.impl.ClientSerializationStreamWriter
  38. * @see com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader
  39. * @see com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter
  40. * @see com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader
  41. */
  42. public class SyncClientSerializationStreamReader extends AbstractSerializationStreamReader{
  43. private static final char JS_ESCAPE_CHAR = '\\';
  44. /**
  45. * Used to accumulate elements while deserializing array types. The generic
  46. * type of the BoundedList will vary from the component type of the array it
  47. * is intended to create when the array is of a primitive type.
  48. *
  49. * @param <T> The type of object used to hold the data in the buffer
  50. */
  51. private static class BoundedList<T> extends LinkedList<T> {
  52. private final Class<?> componentType;
  53. private final int expectedSize;
  54. public BoundedList(Class<?> componentType, int expectedSize) {
  55. this.componentType = componentType;
  56. this.expectedSize = expectedSize;
  57. }
  58. @Override
  59. public boolean add(T o) {
  60. assert size() < getExpectedSize();
  61. return super.add(o);
  62. }
  63. public Class<?> getComponentType() {
  64. return componentType;
  65. }
  66. public int getExpectedSize() {
  67. return expectedSize;
  68. }
  69. }
  70. /**
  71. * Enumeration used to provided typed instance readers.
  72. */
  73. private enum ValueReader {
  74. BOOLEAN {
  75. Object readValue(SyncClientSerializationStreamReader stream)
  76. throws SerializationException {
  77. return stream.readBoolean();
  78. }
  79. },
  80. BYTE {
  81. Object readValue(SyncClientSerializationStreamReader stream)
  82. throws SerializationException {
  83. return stream.readByte();
  84. }
  85. },
  86. CHAR {
  87. Object readValue(SyncClientSerializationStreamReader stream)
  88. throws SerializationException {
  89. return stream.readChar();
  90. }
  91. },
  92. DOUBLE {
  93. Object readValue(SyncClientSerializationStreamReader stream)
  94. throws SerializationException {
  95. return stream.readDouble();
  96. }
  97. },
  98. FLOAT {
  99. Object readValue(SyncClientSerializationStreamReader stream)
  100. throws SerializationException {
  101. return stream.readFloat();
  102. }
  103. },
  104. INT {
  105. Object readValue(SyncClientSerializationStreamReader stream)
  106. throws SerializationException {
  107. return stream.readInt();
  108. }
  109. },
  110. LONG {
  111. Object readValue(SyncClientSerializationStreamReader stream)
  112. throws SerializationException {
  113. return stream.readLong();
  114. }
  115. },
  116. OBJECT {
  117. Object readValue(SyncClientSerializationStreamReader stream)
  118. throws SerializationException {
  119. return stream.readObject();
  120. }
  121. },
  122. SHORT {
  123. Object readValue(SyncClientSerializationStreamReader stream)
  124. throws SerializationException {
  125. return stream.readShort();
  126. }
  127. },
  128. STRING {
  129. Object readValue(SyncClientSerializationStreamReader stream)
  130. throws SerializationException {
  131. return stream.readString();
  132. }
  133. };
  134. abstract Object readValue(SyncClientSerializationStreamReader stream)
  135. throws SerializationException;
  136. }
  137. /**
  138. * Enumeration used to provided typed instance readers for vectors.
  139. */
  140. private enum VectorReader {
  141. BOOLEAN_VECTOR {
  142. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  143. throws SerializationException {
  144. return stream.readBoolean();
  145. }
  146. protected void setSingleValue(Object array, int index, Object value) {
  147. Array.setBoolean(array, index, (Boolean) value);
  148. }
  149. },
  150. BYTE_VECTOR {
  151. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  152. throws SerializationException {
  153. return stream.readByte();
  154. }
  155. protected void setSingleValue(Object array, int index, Object value) {
  156. Array.setByte(array, index, (Byte) value);
  157. }
  158. },
  159. CHAR_VECTOR {
  160. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  161. throws SerializationException {
  162. return stream.readChar();
  163. }
  164. protected void setSingleValue(Object array, int index, Object value) {
  165. Array.setChar(array, index, (Character) value);
  166. }
  167. },
  168. DOUBLE_VECTOR {
  169. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  170. throws SerializationException {
  171. return stream.readDouble();
  172. }
  173. protected void setSingleValue(Object array, int index, Object value) {
  174. Array.setDouble(array, index, (Double) value);
  175. }
  176. },
  177. FLOAT_VECTOR {
  178. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  179. throws SerializationException {
  180. return stream.readFloat();
  181. }
  182. protected void setSingleValue(Object array, int index, Object value) {
  183. Array.setFloat(array, index, (Float) value);
  184. }
  185. },
  186. INT_VECTOR {
  187. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  188. throws SerializationException {
  189. return stream.readInt();
  190. }
  191. protected void setSingleValue(Object array, int index, Object value) {
  192. Array.setInt(array, index, (Integer) value);
  193. }
  194. },
  195. LONG_VECTOR {
  196. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  197. throws SerializationException {
  198. return stream.readLong();
  199. }
  200. protected void setSingleValue(Object array, int index, Object value) {
  201. Array.setLong(array, index, (Long) value);
  202. }
  203. },
  204. OBJECT_VECTOR {
  205. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  206. throws SerializationException {
  207. return stream.readObject();
  208. }
  209. protected void setSingleValue(Object array, int index, Object value) {
  210. Array.set(array, index, value);
  211. }
  212. },
  213. SHORT_VECTOR {
  214. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  215. throws SerializationException {
  216. return stream.readShort();
  217. }
  218. protected void setSingleValue(Object array, int index, Object value) {
  219. Array.setShort(array, index, (Short) value);
  220. }
  221. },
  222. STRING_VECTOR {
  223. protected Object readSingleValue(SyncClientSerializationStreamReader stream)
  224. throws SerializationException {
  225. return stream.readString();
  226. }
  227. protected void setSingleValue(Object array, int index, Object value) {
  228. Array.set(array, index, value);
  229. }
  230. };
  231. protected abstract Object readSingleValue(
  232. SyncClientSerializationStreamReader stream) throws SerializationException;
  233. protected abstract void setSingleValue(Object array, int index, Object value);
  234. /**
  235. * Convert a BoundedList to an array of the correct type. This
  236. * implementation consumes the BoundedList.
  237. */
  238. protected Object toArray(Class<?> componentType, BoundedList<Object> buffer)
  239. throws SerializationException {
  240. if (buffer.getExpectedSize() != buffer.size()) {
  241. throw new SerializationException(
  242. "Inconsistent number of elements received. Received "
  243. + buffer.size() + " but expecting " + buffer.getExpectedSize());
  244. }
  245. Object arr = Array.newInstance(componentType, buffer.size());
  246. for (int i = 0, n = buffer.size(); i < n; i++) {
  247. setSingleValue(arr, i, buffer.removeFirst());
  248. }
  249. return arr;
  250. }
  251. Object read(SyncClientSerializationStreamReader stream,
  252. BoundedList<Object> instance) throws SerializationException {
  253. for (int i = 0, n = instance.getExpectedSize(); i < n; ++i) {
  254. instance.add(readSingleValue(stream));
  255. }
  256. return toArray(instance.getComponentType(), instance);
  257. }
  258. }
  259. /**
  260. * Map of {@link Class} objects to {@link ValueReader}s.
  261. */
  262. private static final Map<Class<?>, ValueReader> CLASS_TO_VALUE_READER = new IdentityHashMap<Class<?>, ValueReader>();
  263. /**
  264. * Map of {@link Class} objects to {@link VectorReader}s.
  265. */
  266. private static final Map<Class<?>, VectorReader> CLASS_TO_VECTOR_READER = new IdentityHashMap<Class<?>, VectorReader>();
  267. {
  268. CLASS_TO_VECTOR_READER.put(boolean[].class, SyncClientSerializationStreamReader.VectorReader.BOOLEAN_VECTOR);
  269. CLASS_TO_VECTOR_READER.put(byte[].class, SyncClientSerializationStreamReader.VectorReader.BYTE_VECTOR);
  270. CLASS_TO_VECTOR_READER.put(char[].class, SyncClientSerializationStreamReader.VectorReader.CHAR_VECTOR);
  271. CLASS_TO_VECTOR_READER.put(double[].class, SyncClientSerializationStreamReader.VectorReader.DOUBLE_VECTOR);
  272. CLASS_TO_VECTOR_READER.put(float[].class, SyncClientSerializationStreamReader.VectorReader.FLOAT_VECTOR);
  273. CLASS_TO_VECTOR_READER.put(int[].class, SyncClientSerializationStreamReader.VectorReader.INT_VECTOR);
  274. CLASS_TO_VECTOR_READER.put(long[].class, SyncClientSerializationStreamReader.VectorReader.LONG_VECTOR);
  275. CLASS_TO_VECTOR_READER.put(Object[].class, SyncClientSerializationStreamReader.VectorReader.OBJECT_VECTOR);
  276. CLASS_TO_VECTOR_READER.put(short[].class, SyncClientSerializationStreamReader.VectorReader.SHORT_VECTOR);
  277. CLASS_TO_VECTOR_READER.put(String[].class, SyncClientSerializationStreamReader.VectorReader.STRING_VECTOR);
  278. CLASS_TO_VALUE_READER.put(boolean.class, SyncClientSerializationStreamReader.ValueReader.BOOLEAN);
  279. CLASS_TO_VALUE_READER.put(byte.class, SyncClientSerializationStreamReader.ValueReader.BYTE);
  280. CLASS_TO_VALUE_READER.put(char.class, SyncClientSerializationStreamReader.ValueReader.CHAR);
  281. CLASS_TO_VALUE_READER.put(double.class, SyncClientSerializationStreamReader.ValueReader.DOUBLE);
  282. CLASS_TO_VALUE_READER.put(float.class, SyncClientSerializationStreamReader.ValueReader.FLOAT);
  283. CLASS_TO_VALUE_READER.put(int.class, SyncClientSerializationStreamReader.ValueReader.INT);
  284. CLASS_TO_VALUE_READER.put(long.class, SyncClientSerializationStreamReader.ValueReader.LONG);
  285. CLASS_TO_VALUE_READER.put(Object.class, SyncClientSerializationStreamReader.ValueReader.OBJECT);
  286. CLASS_TO_VALUE_READER.put(short.class, SyncClientSerializationStreamReader.ValueReader.SHORT);
  287. CLASS_TO_VALUE_READER.put(String.class, SyncClientSerializationStreamReader.ValueReader.STRING);
  288. }
  289. private List<String> results = new ArrayList<String>();
  290. private int index;
  291. private List<String> stringTable = new ArrayList<String>();
  292. private SerializationPolicy serializationPolicy;
  293. public SyncClientSerializationStreamReader(SerializationPolicy serializationPolicy) {
  294. this.serializationPolicy = serializationPolicy;
  295. }
  296. @Override
  297. public void prepareToRead(String encoded) throws SerializationException {
  298. encoded = deconcat(encoded);
  299. parse(encoded);
  300. index = results.size();
  301. super.prepareToRead(encoded);
  302. if ((getVersion() < SERIALIZATION_STREAM_MIN_VERSION)
  303. || (getVersion() > SERIALIZATION_STREAM_VERSION)) {
  304. throw new IncompatibleRemoteServiceException("Expecting version between "
  305. + SERIALIZATION_STREAM_MIN_VERSION + " and "
  306. + SERIALIZATION_STREAM_VERSION + " from server, got " + getVersion()
  307. + ".");
  308. }
  309. buildStringTable();
  310. }
  311. protected Object deserialize(String typeSignature) throws SerializationException{
  312. Object instance = null;
  313. SerializedInstanceReference serializedInstRef = SerializabilityUtil.decodeSerializedInstanceReference(typeSignature);
  314. try {
  315. // Class<?> instanceClass = Class.forName(serializedInstRef.getName(),
  316. // false, null);
  317. Class<?> instanceClass = Class.forName(serializedInstRef.getName());
  318. assert (serializationPolicy != null);
  319. try{
  320. serializationPolicy.validateDeserialize(instanceClass);
  321. }catch(SerializationException e){
  322. System.err.println("WARN: " + e.getMessage());
  323. }
  324. //TODO validateTypeVersions(instanceClass, serializedInstRef);
  325. Class<?> customSerializer = SerializabilityUtil.hasCustomFieldSerializer(instanceClass);
  326. int index = reserveDecodedObjectIndex();
  327. instance = instantiate(customSerializer, instanceClass);
  328. rememberDecodedObject(index, instance);
  329. Object replacement = deserializeImpl(customSerializer, instanceClass,
  330. instance);
  331. // It's possible that deserializing an object requires the original proxy
  332. // object to be replaced.
  333. if (instance != replacement) {
  334. rememberDecodedObject(index, replacement);
  335. instance = replacement;
  336. }
  337. return instance;
  338. } catch (ClassNotFoundException e) {
  339. throw new SerializationException(e);
  340. } catch (InstantiationException e) {
  341. throw new SerializationException(e);
  342. } catch (IllegalAccessException e) {
  343. throw new SerializationException(e);
  344. } catch (IllegalArgumentException e) {
  345. throw new SerializationException(e);
  346. } catch (InvocationTargetException e) {
  347. throw new SerializationException(e);
  348. } catch (NoSuchMethodException e) {
  349. throw new SerializationException(e);
  350. }
  351. }
  352. protected String getString(int index) {
  353. if (index == 0) {
  354. return null;
  355. }
  356. // index is 1-based
  357. assert (index > 0);
  358. assert (index <= stringTable.size());
  359. // index is 1-based
  360. return this.stringTable.get(index-1);
  361. }
  362. public boolean readBoolean() {
  363. return !results.get(--index).equals("0");
  364. }
  365. public byte readByte() {
  366. return Byte.parseByte(results.get(--index));
  367. }
  368. public char readChar() {
  369. return (char)Integer.parseInt(results.get(--index));
  370. }
  371. public double readDouble() {
  372. return Double.parseDouble(results.get(--index));
  373. }
  374. public float readFloat() {
  375. return Float.parseFloat(results.get(--index));
  376. }
  377. public int readInt() {
  378. return Integer.parseInt(results.get(--index));
  379. }
  380. public long readLong() {
  381. if (getVersion() == SERIALIZATION_STREAM_MIN_VERSION) {
  382. return (long) readDouble() + (long) readDouble();
  383. }else{
  384. String s = results.get(--index);
  385. // remove quotes
  386. s = s.substring(1, s.length() - 1);
  387. return Utils.longFromBase64(s);
  388. }
  389. }
  390. public short readShort() {
  391. return Short.parseShort(results.get(--index));
  392. }
  393. public String readString() {
  394. return getString(readInt());
  395. }
  396. /**
  397. * Parse response from GWT RPC
  398. * example: [3,23456,0,2,0,0,0,1,1,["dab.rpp.client.Person/1455343364","My dad name","GWT User"],0,5]
  399. * @param encoded
  400. */
  401. private void parse(String encoded){
  402. // encoded = encoded.substring(1, encoded.length()-1);
  403. if (encoded.endsWith("]")){
  404. encoded = encoded.substring(1, encoded.length()-1);
  405. }else{
  406. encoded = encoded.substring(1);
  407. }
  408. StringBuffer token = new StringBuffer();
  409. for (int i=0; i<encoded.length(); i++){
  410. char ch = encoded.charAt(i);
  411. if (ch == ','){
  412. results.add(token.toString());
  413. token = new StringBuffer();
  414. continue;
  415. }
  416. if (ch == '['){
  417. int pos = encoded.lastIndexOf(']');
  418. if (pos < 0){
  419. // TODO: throw exeption
  420. }
  421. results.add(encoded.substring(i+1, pos));
  422. i = pos+1;
  423. continue;
  424. }
  425. token.append(ch);
  426. }
  427. if (token.length() > 0){
  428. results.add(token.toString());
  429. }
  430. }
  431. private static final String PRELUDE = "].concat([";
  432. private static final String POSTLUDE1 = "],[";
  433. private static final String POSTLUDE = "])";
  434. private String deconcat(String encoded) {
  435. int start = encoded.indexOf(PRELUDE);
  436. if (start > 0){
  437. StringBuffer ret = new StringBuffer(encoded.length() - PRELUDE.length());
  438. ret.append(encoded.substring(0, start));
  439. start += PRELUDE.length();
  440. int end = encoded.indexOf(POSTLUDE1, start);
  441. while (end > 0){
  442. ret.append(",");
  443. ret.append(encoded.substring(start, end));
  444. start = end + POSTLUDE1.length();
  445. end = encoded.indexOf(POSTLUDE1, start);
  446. }
  447. end = encoded.indexOf(POSTLUDE, start);
  448. if (end > 0){
  449. ret.append(",");
  450. ret.append(encoded.substring(start, end+1));
  451. return ret.toString();
  452. }
  453. }
  454. return encoded;
  455. }
  456. private Object instantiate(Class<?> customSerializer, Class<?> instanceClass)
  457. throws InstantiationException, IllegalAccessException,
  458. IllegalArgumentException, InvocationTargetException,
  459. NoSuchMethodException, SerializationException {
  460. if (customSerializer != null) {
  461. for (Method method : customSerializer.getMethods()) {
  462. if ("instantiate".equals(method.getName())) {
  463. return method.invoke(null, this);
  464. }
  465. }
  466. // Ok to not have one.
  467. }
  468. if (instanceClass.isArray()) {
  469. int length = readInt();
  470. // We don't pre-allocate the array; this prevents an allocation attack
  471. return new BoundedList<Object>(instanceClass.getComponentType(), length);
  472. } else if (instanceClass.isEnum()) {
  473. Enum<?>[] enumConstants = (Enum[]) instanceClass.getEnumConstants();
  474. int ordinal = readInt();
  475. assert (ordinal >= 0 && ordinal < enumConstants.length);
  476. return enumConstants[ordinal];
  477. } else {
  478. Constructor<?> constructor = instanceClass.getDeclaredConstructor();
  479. constructor.setAccessible(true);
  480. return constructor.newInstance();
  481. }
  482. }
  483. private Object deserializeImpl(Class<?> customSerializer,
  484. Class<?> instanceClass, Object instance) throws NoSuchMethodException,
  485. IllegalArgumentException, IllegalAccessException,
  486. InvocationTargetException, SerializationException, ClassNotFoundException {
  487. if (customSerializer != null) {
  488. deserializeWithCustomFieldDeserializer(customSerializer, instanceClass,
  489. instance);
  490. } else if (instanceClass.isArray()) {
  491. instance = deserializeArray(instanceClass, instance);
  492. } else if (instanceClass.isEnum()) {
  493. // Enums are deserialized when they are instantiated
  494. } else {
  495. deserializeClass(instanceClass, instance);
  496. }
  497. return instance;
  498. }
  499. private void deserializeWithCustomFieldDeserializer(
  500. Class<?> customSerializer, Class<?> instanceClass, Object instance)
  501. throws NoSuchMethodException, IllegalAccessException,
  502. InvocationTargetException {
  503. assert (!instanceClass.isArray());
  504. for (Method method : customSerializer.getMethods()) {
  505. if ("deserialize".equals(method.getName())) {
  506. method.invoke(null, this, instance);
  507. return;
  508. }
  509. }
  510. throw new NoSuchMethodException("deserialize");
  511. }
  512. /**
  513. * Deserialize an instance that is an array. Will default to deserializing as
  514. * an Object vector if the instance is not a primitive vector.
  515. *
  516. * @param instanceClass
  517. * @param instance
  518. * @throws SerializationException
  519. */
  520. @SuppressWarnings("unchecked")
  521. private Object deserializeArray(Class<?> instanceClass, Object instance)
  522. throws SerializationException {
  523. assert (instanceClass.isArray());
  524. BoundedList<Object> buffer = (BoundedList<Object>) instance;
  525. VectorReader instanceReader = CLASS_TO_VECTOR_READER.get(instanceClass);
  526. if (instanceReader != null) {
  527. return instanceReader.read(this, buffer);
  528. } else {
  529. return SyncClientSerializationStreamReader.VectorReader.OBJECT_VECTOR.read(this, buffer);
  530. }
  531. }
  532. private void deserializeClass(Class<?> instanceClass, Object instance)
  533. throws SerializationException, IllegalAccessException,
  534. NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
  535. Field[] serializableFields = SerializabilityUtil.applyFieldSerializationPolicy(instanceClass);
  536. for (Field declField : serializableFields) {
  537. assert (declField != null);
  538. Object value = deserializeValue(declField.getType());
  539. boolean isAccessible = declField.isAccessible();
  540. boolean needsAccessOverride = !isAccessible
  541. && !Modifier.isPublic(declField.getModifiers());
  542. if (needsAccessOverride) {
  543. // Override access restrictions
  544. declField.setAccessible(true);
  545. }
  546. declField.set(instance, value);
  547. }
  548. Class<?> superClass = instanceClass.getSuperclass();
  549. if (serializationPolicy.shouldDeserializeFields(superClass)) {
  550. deserializeImpl(SerializabilityUtil.hasCustomFieldSerializer(superClass),
  551. superClass, instance);
  552. }
  553. }
  554. public Object deserializeValue(Class<?> type) throws SerializationException {
  555. ValueReader valueReader = CLASS_TO_VALUE_READER.get(type);
  556. if (valueReader != null) {
  557. return valueReader.readValue(this);
  558. } else {
  559. // Arrays of primitive or reference types need to go through readObject.
  560. return SyncClientSerializationStreamReader.ValueReader.OBJECT.readValue(this);
  561. }
  562. }
  563. private void buildStringTable(){
  564. String raw = results.get(--index);
  565. byte b1; byte b2; byte b3; byte b4;
  566. boolean startNewString = true;
  567. StringBuffer buffer = new StringBuffer();
  568. for (int i=0; i<raw.length(); i++){
  569. char ch = raw.charAt(i);
  570. if (startNewString){
  571. assert ch == '\"';
  572. startNewString = false;
  573. continue;
  574. }
  575. if (ch == '\"'){ // end-of-string
  576. this.stringTable.add(buffer.toString());
  577. buffer.setLength(0);
  578. startNewString = true;
  579. if (i != raw.length()-1){
  580. assert raw.charAt(i+1) == ',';
  581. i++;
  582. }
  583. continue;
  584. }
  585. if (ch == JS_ESCAPE_CHAR){
  586. i++;
  587. ch = raw.charAt(i);
  588. switch(ch){
  589. case '0': // \0
  590. buffer.append('\u0000');
  591. break;
  592. case 'b': // \b
  593. buffer.append('\b');
  594. break;
  595. case 't': // \t
  596. buffer.append('\t');
  597. break;
  598. case 'n': // \n
  599. buffer.append('\n');
  600. break;
  601. case 'f': // \f
  602. buffer.append('\f');
  603. break;
  604. case 'r': // \r
  605. buffer.append('\r');
  606. break;
  607. case '\"': // \"
  608. buffer.append('\"');
  609. break;
  610. case '\\': // \\
  611. buffer.append('\\');
  612. break;
  613. case 'x': // \\xNN
  614. b1 = hex2byte(raw.charAt(++i));
  615. b2 = hex2byte(raw.charAt(++i));
  616. ch = (char)(b1*16 + b2);
  617. buffer.append(ch);
  618. break;
  619. case 'u': // \\uNNNN
  620. b1 = hex2byte(raw.charAt(++i));
  621. b2 = hex2byte(raw.charAt(++i));
  622. b3 = hex2byte(raw.charAt(++i));
  623. b4 = hex2byte(raw.charAt(++i));
  624. ch = (char)(b1*16*16*16 + b2*16*16 + b3*16 + b4);
  625. buffer.append(ch);
  626. break;
  627. default:
  628. // TODO:
  629. System.out.println("???");
  630. }
  631. }else{
  632. buffer.append(ch);
  633. }
  634. }
  635. }
  636. private byte hex2byte(char ch){
  637. if ((ch >= '0') && (ch <= '9')){
  638. return (byte)(ch-'0');
  639. }
  640. if ((ch >= 'A') && (ch <= 'F')){
  641. return (byte)(ch-'A'+10);
  642. }
  643. if ((ch >= 'a') && (ch <= 'f')){
  644. return (byte)(ch-'a'+10);
  645. }
  646. return -1;
  647. }
  648. public static void main(String[] args) throws Exception{
  649. BufferedReader reader = new BufferedReader(new FileReader("C:/temp/large.txt"));
  650. String encoded = reader.readLine();
  651. SyncClientSerializationStreamReader s = new SyncClientSerializationStreamReader(new RemoteServiceSyncProxy.DummySerializationPolicy());
  652. s.prepareToRead(encoded);
  653. }
  654. }