blob: 923694edf2e891cab2b3295a91d544ae13c16047 [file] [log] [blame]
Jerome Poichet7c997852014-05-20 10:50:05 -07001/*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.polo.wire.json;
18
19import com.google.polo.exception.PoloException;
20import com.google.polo.json.JSONException;
21import com.google.polo.json.JSONObject;
22import com.google.polo.pairing.PairingContext;
23import com.google.polo.pairing.PoloUtil;
24import com.google.polo.pairing.message.PoloMessage;
25import com.google.polo.pairing.message.PoloMessage.PoloMessageType;
26import com.google.polo.wire.PoloWireInterface;
27
28import java.io.DataInputStream;
29import java.io.DataOutputStream;
30import java.io.IOException;
31import java.io.InputStream;
32import java.io.OutputStream;
33
34/**
35 * A {@link PoloWireInterface} which uses JavaScript Object Notation (JSON) for
36 * the message representation.
37 * <p>
38 * Messages are streamed over the wire prepended with an integer which indicates
39 * the total length, in bytes, of the message which follows. The format of the
40 * message is JSON.
41 * <p>
42 * See {@link JsonMessageBuilder} for the underlying message translation
43 * implementation.
44 */
45public class JsonWireAdapter implements PoloWireInterface {
46
47 /**
48 * The output coming from the peer.
49 */
50 private final DataInputStream mInputStream;
51
52 /**
53 * The input going to the peer.
54 */
55 private final DataOutputStream mOutputStream;
56
57 /**
58 * Constructor.
Jerome Poichet22c862e2014-07-02 15:19:20 -070059 *
Jerome Poichet7c997852014-05-20 10:50:05 -070060 * @param input the {@link InputStream} from the peer
61 * @param output the {@link OutputStream} to the peer
62 */
63 public JsonWireAdapter(InputStream input, OutputStream output) {
64 mInputStream = new DataInputStream(input);
65 mOutputStream = new DataOutputStream(output);
66 }
67
68 /**
69 * Generates a new instance from a {@link PairingContext}.
Jerome Poichet22c862e2014-07-02 15:19:20 -070070 *
Jerome Poichet7c997852014-05-20 10:50:05 -070071 * @param context the {@link PairingContext}
72 * @return the new instance
73 */
74 public static JsonWireAdapter fromContext(PairingContext context) {
75 return new JsonWireAdapter(context.getPeerInputStream(), context
76 .getPeerOutputStream());
77 }
78
79 public PoloMessage getNextMessage() throws IOException, PoloException {
80 byte[] payloadLenBytes = new byte[4];
81 mInputStream.readFully(payloadLenBytes);
82 long payloadLen = PoloUtil.intBigEndianBytesToLong(payloadLenBytes);
83 byte[] outerJsonBytes = new byte[(int) payloadLen];
84 mInputStream.readFully(outerJsonBytes);
85 return parseOuterMessageString(new String(outerJsonBytes));
86 }
87
88 public PoloMessage parseOuterMessageString(String outerString)
89 throws PoloException {
90 JSONObject outerMessage;
91 try {
92 outerMessage = new JSONObject(outerString);
93 } catch (JSONException e) {
94 throw new PoloException("Error parsing incoming message", e);
95 }
96 return JsonMessageBuilder.outerJsonToPoloMessage(outerMessage);
97 }
98
99 public PoloMessage getNextMessage(PoloMessageType type) throws IOException,
100 PoloException {
101 PoloMessage message = getNextMessage();
102 if (message.getType() != type) {
103 throw new PoloException("Wrong message type (wanted " + type + ", got "
104 + message.getType() + ")");
105 }
106 return message;
107 }
108
109 public void sendErrorMessage(Exception exception) throws IOException {
110 try {
111 writeJson(JsonMessageBuilder.getErrorJson(exception));
112 } catch (PoloException e) {
113 throw new IOException("Error sending error message");
114 }
115 }
116
117 public void sendMessage(PoloMessage message) throws IOException {
118 String outString;
119 JSONObject outerJson;
120
121 try {
122 outerJson = JsonMessageBuilder.getOuterJson(message);
123 } catch (PoloException e) {
124 throw new IOException("Error generating message");
125 }
126
Jerome Poichet7c997852014-05-20 10:50:05 -0700127 writeJson(outerJson);
128 }
129
130 /**
131 * Writes a {@link JSONObject} to the output stream as a {@link String}.
Jerome Poichet22c862e2014-07-02 15:19:20 -0700132 *
Jerome Poichet7c997852014-05-20 10:50:05 -0700133 * @param message the message to write
134 * @throws IOException on error generating the serialized message
135 */
136 private void writeJson(JSONObject message) throws IOException {
137 byte[] outBytes = message.toString().getBytes();
138 mOutputStream.write(PoloUtil.intToBigEndianIntBytes(outBytes.length));
139 mOutputStream.write(outBytes);
140 }
141
142}