Home | History | Annotate | Download | only in xml
      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