17c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/* 27c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Copyright (C) 2009 Google Inc. All rights reserved. 37c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 47c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Licensed under the Apache License, Version 2.0 (the "License"); 57c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * you may not use this file except in compliance with the License. 67c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * You may obtain a copy of the License at 77c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 87c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * http://www.apache.org/licenses/LICENSE-2.0 97c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * 107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Unless required by applicable law or agreed to in writing, software 117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * distributed under the License is distributed on an "AS IS" BASIS, 127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * See the License for the specific language governing permissions and 147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * limitations under the License. 157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpackage com.google.polo.wire.json; 187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.exception.PoloException; 207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.json.JSONException; 217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.json.JSONObject; 227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.pairing.PairingContext; 237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.pairing.PoloUtil; 247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.pairing.message.PoloMessage; 257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.pairing.message.PoloMessage.PoloMessageType; 267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport com.google.polo.wire.PoloWireInterface; 277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.DataInputStream; 297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.DataOutputStream; 307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.IOException; 317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.InputStream; 327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetimport java.io.OutputStream; 337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet/** 357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * A {@link PoloWireInterface} which uses JavaScript Object Notation (JSON) for 367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * the message representation. 377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * <p> 387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Messages are streamed over the wire prepended with an integer which indicates 397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * the total length, in bytes, of the message which follows. The format of the 407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * message is JSON. 417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * <p> 427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * See {@link JsonMessageBuilder} for the underlying message translation 437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * implementation. 447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetpublic class JsonWireAdapter implements PoloWireInterface { 467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * The output coming from the peer. 497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private final DataInputStream mInputStream; 517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * The input going to the peer. 547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private final DataOutputStream mOutputStream; 567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Constructor. 5922c862eaf3f88bb389c3b53b1f7a22415da7177eJerome Poichet * 607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param input the {@link InputStream} from the peer 617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param output the {@link OutputStream} to the peer 627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public JsonWireAdapter(InputStream input, OutputStream output) { 647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mInputStream = new DataInputStream(input); 657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mOutputStream = new DataOutputStream(output); 667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Generates a new instance from a {@link PairingContext}. 7022c862eaf3f88bb389c3b53b1f7a22415da7177eJerome Poichet * 717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param context the {@link PairingContext} 727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @return the new instance 737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public static JsonWireAdapter fromContext(PairingContext context) { 757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return new JsonWireAdapter(context.getPeerInputStream(), context 767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet .getPeerOutputStream()); 777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public PoloMessage getNextMessage() throws IOException, PoloException { 807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet byte[] payloadLenBytes = new byte[4]; 817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mInputStream.readFully(payloadLenBytes); 827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet long payloadLen = PoloUtil.intBigEndianBytesToLong(payloadLenBytes); 837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet byte[] outerJsonBytes = new byte[(int) payloadLen]; 847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mInputStream.readFully(outerJsonBytes); 857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return parseOuterMessageString(new String(outerJsonBytes)); 867c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 877c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 887c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public PoloMessage parseOuterMessageString(String outerString) 897c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throws PoloException { 907c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet JSONObject outerMessage; 917c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 927c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outerMessage = new JSONObject(outerString); 937c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (JSONException e) { 947c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new PoloException("Error parsing incoming message", e); 957c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 967c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return JsonMessageBuilder.outerJsonToPoloMessage(outerMessage); 977c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 987c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 997c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public PoloMessage getNextMessage(PoloMessageType type) throws IOException, 1007c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet PoloException { 1017c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet PoloMessage message = getNextMessage(); 1027c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet if (message.getType() != type) { 1037c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new PoloException("Wrong message type (wanted " + type + ", got " 1047c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet + message.getType() + ")"); 1057c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1067c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet return message; 1077c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1087c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1097c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public void sendErrorMessage(Exception exception) throws IOException { 1107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 1117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet writeJson(JsonMessageBuilder.getErrorJson(exception)); 1127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (PoloException e) { 1137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new IOException("Error sending error message"); 1147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet public void sendMessage(PoloMessage message) throws IOException { 1187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet String outString; 1197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet JSONObject outerJson; 1207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet try { 1227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet outerJson = JsonMessageBuilder.getOuterJson(message); 1237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } catch (PoloException e) { 1247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet throw new IOException("Error generating message"); 1257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet writeJson(outerJson); 1287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet /** 1317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * Writes a {@link JSONObject} to the output stream as a {@link String}. 13222c862eaf3f88bb389c3b53b1f7a22415da7177eJerome Poichet * 1337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @param message the message to write 1347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet * @throws IOException on error generating the serialized message 1357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet */ 1367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet private void writeJson(JSONObject message) throws IOException { 1377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet byte[] outBytes = message.toString().getBytes(); 1387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mOutputStream.write(PoloUtil.intToBigEndianIntBytes(outBytes.length)); 1397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet mOutputStream.write(outBytes); 1407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet } 1417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet 1427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet} 143