• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.google.polo.wire.json;
18 
19 import com.google.polo.exception.PoloException;
20 import com.google.polo.json.JSONException;
21 import com.google.polo.json.JSONObject;
22 import com.google.polo.pairing.PairingContext;
23 import com.google.polo.pairing.PoloUtil;
24 import com.google.polo.pairing.message.PoloMessage;
25 import com.google.polo.pairing.message.PoloMessage.PoloMessageType;
26 import com.google.polo.wire.PoloWireInterface;
27 
28 import java.io.DataInputStream;
29 import java.io.DataOutputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import 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  */
45 public 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.
59    *
60    * @param input the {@link InputStream} from the peer
61    * @param output the {@link OutputStream} to the peer
62    */
JsonWireAdapter(InputStream input, OutputStream output)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}.
70    *
71    * @param context the {@link PairingContext}
72    * @return the new instance
73    */
fromContext(PairingContext context)74   public static JsonWireAdapter fromContext(PairingContext context) {
75     return new JsonWireAdapter(context.getPeerInputStream(), context
76         .getPeerOutputStream());
77   }
78 
getNextMessage()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 
parseOuterMessageString(String outerString)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 
getNextMessage(PoloMessageType type)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 
sendErrorMessage(Exception exception)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 
sendMessage(PoloMessage message)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 
127     writeJson(outerJson);
128   }
129 
130   /**
131    * Writes a {@link JSONObject} to the output stream as a {@link String}.
132    *
133    * @param  message      the message to write
134    * @throws IOException  on error generating the serialized message
135    */
writeJson(JSONObject message)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 }
143