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.xml; 18 19 import com.google.polo.exception.PoloException; 20 import com.google.polo.pairing.HexDump; 21 import com.google.polo.pairing.PairingContext; 22 import com.google.polo.pairing.message.PoloMessage; 23 import com.google.polo.pairing.message.PoloMessage.PoloMessageType; 24 import com.google.polo.wire.PoloWireInterface; 25 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.OutputStream; 29 30 public class XmlWireAdapter implements PoloWireInterface { 31 32 /** 33 * Enables extra verbose debug logging. 34 */ 35 private static final boolean DEBUG_VERBOSE = false; 36 37 private static final int STATUS_OK = 1; 38 39 /** 40 * The output coming from the peer. 41 */ 42 private final InputStream mInputStream; 43 44 /** 45 * The input going to the peer. 46 */ 47 private final OutputStream mOutputStream; 48 49 private final XmlMessageBuilder mBuilder; 50 51 /** 52 * Constructor. 53 * 54 * @param input the {@link InputStream} from the peer 55 * @param output the {@link OutputStream} to the peer 56 */ 57 public XmlWireAdapter(InputStream input, OutputStream output) { 58 mInputStream = input; 59 mOutputStream = output; 60 mBuilder = new XmlMessageBuilder(); 61 } 62 63 /** 64 * Generates a new instance from a {@link PairingContext}. 65 * @param context the {@link PairingContext} 66 * @return the new instance 67 */ 68 public static XmlWireAdapter fromContext(PairingContext context) { 69 return new XmlWireAdapter(context.getPeerInputStream(), 70 context.getPeerOutputStream()); 71 } 72 73 public PoloMessage getNextMessage() throws IOException, PoloException { 74 XmlMessageWrapper outerMessage = 75 XmlMessageWrapper.fromInputStream(mInputStream); 76 if (DEBUG_VERBOSE) { 77 debug(">>> Incoming Message:"); 78 debug(HexDump.dumpHexString(outerMessage.serializeToByteArray())); 79 } 80 81 String outerXML = new String(outerMessage.getPayload()); 82 return mBuilder.outerXMLToPoloMessage(outerXML); 83 } 84 85 public PoloMessage getNextMessage(PoloMessageType type) throws IOException, PoloException { 86 PoloMessage message = getNextMessage(); 87 if (message.getType() != type) { 88 throw new PoloException("Wrong message type (wanted " + type + 89 ", got " + message.getType() + ")"); 90 } 91 return message; 92 } 93 94 public void sendErrorMessage(Exception exception) throws IOException { 95 String errorXml; 96 try { 97 errorXml = mBuilder.getErrorXML(exception); 98 } catch (PoloException e) { 99 // just ignore it; nothing we can do 100 return; 101 } 102 byte[] outBytes = errorXml.getBytes(); 103 XmlMessageWrapper message = new XmlMessageWrapper("client", 1, 104 (byte) 0, outBytes); 105 writeXML(message); 106 } 107 108 public void sendMessage(PoloMessage poloMessage) throws IOException { 109 String outString = mBuilder.getOuterXML(poloMessage, STATUS_OK); 110 111 // NOTE(mikey): A particular parser is very sensitive to newline 112 // placement. Strip all newlines, then add them to separate adjacent 113 // XML entities. 114 outString = outString.replace("\n", ""); 115 outString = outString.replace("><", ">\n<"); 116 117 byte[] outBytes = outString.getBytes(); 118 XmlMessageWrapper message = new XmlMessageWrapper("client", 1, 119 (byte) 0, outBytes); 120 writeXML(message); 121 } 122 123 /** 124 * Writes a {@link XmlMessageWrapper} to the output stream as a 125 * {@link String}. 126 * 127 * @param message the message to write 128 * @throws IOException on error generating the serialized message 129 */ 130 private void writeXML(XmlMessageWrapper message) throws IOException { 131 if (DEBUG_VERBOSE) { 132 debug("<<< Outgoing Message:"); 133 debug(HexDump.dumpHexString(message.serializeToByteArray())); 134 } 135 mOutputStream.write(message.serializeToByteArray()); 136 } 137 138 private void debug(String message) { 139 System.out.println(message); 140 } 141 142 } 143