/* * Copyright (C) 2009 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.polo.wire.xml; import com.google.polo.exception.PoloException; import com.google.polo.pairing.HexDump; import com.google.polo.pairing.PairingContext; import com.google.polo.pairing.message.PoloMessage; import com.google.polo.pairing.message.PoloMessage.PoloMessageType; import com.google.polo.wire.PoloWireInterface; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class XmlWireAdapter implements PoloWireInterface { /** * Enables extra verbose debug logging. */ private static final boolean DEBUG_VERBOSE = false; private static final int STATUS_OK = 1; /** * The output coming from the peer. */ private final InputStream mInputStream; /** * The input going to the peer. */ private final OutputStream mOutputStream; private final XmlMessageBuilder mBuilder; /** * Constructor. * * @param input the {@link InputStream} from the peer * @param output the {@link OutputStream} to the peer */ public XmlWireAdapter(InputStream input, OutputStream output) { mInputStream = input; mOutputStream = output; mBuilder = new XmlMessageBuilder(); } /** * Generates a new instance from a {@link PairingContext}. * @param context the {@link PairingContext} * @return the new instance */ public static XmlWireAdapter fromContext(PairingContext context) { return new XmlWireAdapter(context.getPeerInputStream(), context.getPeerOutputStream()); } public PoloMessage getNextMessage() throws IOException, PoloException { XmlMessageWrapper outerMessage = XmlMessageWrapper.fromInputStream(mInputStream); if (DEBUG_VERBOSE) { debug(">>> Incoming Message:"); debug(HexDump.dumpHexString(outerMessage.serializeToByteArray())); } String outerXML = new String(outerMessage.getPayload()); return mBuilder.outerXMLToPoloMessage(outerXML); } public PoloMessage getNextMessage(PoloMessageType type) throws IOException, PoloException { PoloMessage message = getNextMessage(); if (message.getType() != type) { throw new PoloException("Wrong message type (wanted " + type + ", got " + message.getType() + ")"); } return message; } public void sendErrorMessage(Exception exception) throws IOException { String errorXml; try { errorXml = mBuilder.getErrorXML(exception); } catch (PoloException e) { // just ignore it; nothing we can do return; } byte[] outBytes = errorXml.getBytes(); XmlMessageWrapper message = new XmlMessageWrapper("client", 1, (byte) 0, outBytes); writeXML(message); } public void sendMessage(PoloMessage poloMessage) throws IOException { String outString = mBuilder.getOuterXML(poloMessage, STATUS_OK); // NOTE(mikey): A particular parser is very sensitive to newline // placement. Strip all newlines, then add them to separate adjacent // XML entities. outString = outString.replace("\n", ""); outString = outString.replace("><", ">\n<"); byte[] outBytes = outString.getBytes(); XmlMessageWrapper message = new XmlMessageWrapper("client", 1, (byte) 0, outBytes); writeXML(message); } /** * Writes a {@link XmlMessageWrapper} to the output stream as a * {@link String}. * * @param message the message to write * @throws IOException on error generating the serialized message */ private void writeXML(XmlMessageWrapper message) throws IOException { if (DEBUG_VERBOSE) { debug("<<< Outgoing Message:"); debug(HexDump.dumpHexString(message.serializeToByteArray())); } mOutputStream.write(message.serializeToByteArray()); } private void debug(String message) { System.out.println(message); } }