⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packetencoder.java

📁 MegaMek is a networked Java clone of BattleTech, a turn-based sci-fi boardgame for 2+ players. Fight
💻 JAVA
字号:
/* * MegaMek - Copyright (C) 2003 Ben Mazur (bmazur@sev.org) *  *  This program is free software; you can redistribute it and/or modify it  *  under the terms of the GNU General Public License as published by the Free  *  Software Foundation; either version 2 of the License, or (at your option)  *  any later version. *  *  This program is distributed in the hope that it will be useful, but  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License  *  for more details. */package megamek.common.xml;import java.io.*;import megamek.common.*;import megamek.common.net.Packet;import com.Ostermiller.util.Base64;import gd.xml.ParseException;import gd.xml.tiny.TinyParser;import gd.xml.tiny.ParsedXML;import java.util.Enumeration;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;/** * Objects of this class can encode a <code>Packet</code> object as XML * into an output writer and decode one from a parsed XML node.  It is used * when saving games into a version- neutral format. * * @author      James Damour <suvarov454@users.sourceforge.net> */public class PacketEncoder {    /**     * Dummy tag to start an un-zipped data element stream.     */    private static final String START = "<dummy>";    /**     * Dummy tag to end an un-zipped data element stream.     */    private static final String END = "</dummy>";    /**     * Helper function to encode the packet's data.     *     * @param   packet - the <code>Packet</code> to be encoded.     *          This value must not be <code>null</code>.     * @param   out - the <code>Writer</code> that will receive the XML.     *          This value must not be <code>null</code>.     * @throws  <code>IllegalArgumentException</code> if the node is     *          <code>null</code>.     * @throws  <code>IOException</code> if there's any error on write.     */    private static void encodeData( Packet packet, Writer out )        throws IOException    {        // Packet data encoding is based on data type.        Object[] data = packet.getData();        for ( int loop = 0; loop < data.length; loop++ ) {            if ( null == data[loop] ) {                out.write( "<null />" );            }            else if ( data[loop].getClass().equals(Integer.class) ) {                out.write( "<integer value=\"" );                out.write( data[loop].toString() );                out.write( "\" />" );            }            else if ( data[loop].getClass().equals(IBoard.class) ) {                BoardEncoder.encode( (Board) data[loop], out );            }        }    }    /**     * Helper function to decode the packet's data.     *     * @param   node - the <code>ParsedXML</code> node for this object.     *          This value must not be <code>null</code>.     * @param   game - the <code>IGame</code> the decoded object belongs to.     * @return  the <code>Object</code> corresponding to the node.     *          This value may be <code>null</code>.     * @throws  <code>IllegalArgumentException</code> if the node is     *          <code>null</code>.     * @throws  <code>IllegalStateException</code> if the node does not     *          contain a valid <code>Packet</code>.     * @throws  <code>NumberFormatException</code> if the value of a numeric     *          data element is not in a valid format.     */    private static Object decodeData( ParsedXML node, IGame game ) {        Object retval = null;        // Decoding is base the node's name.        if ( node.getName().equals( "null" ) ) {            retval = null;        }        else if ( node.getName().equals( "integer" ) ) {            retval = new Integer( node.getAttribute("value") );        }        else if ( node.getName().equals( "board" ) ) {            retval = BoardEncoder.decode( node, game );        }        return retval;    }    /**     * Encode a <code>Packet</code> object to an output writer.     *     * @param   packet - the <code>Packet</code> to be encoded.     *          This value must not be <code>null</code>.     * @param   out - the <code>Writer</code> that will receive the XML.     *          This value must not be <code>null</code>.     * @throws  <code>IllegalArgumentException</code> if the node is     *          <code>null</code>.     * @throws  <code>IOException</code> if there's any error on write.     */    public static void encode( Packet packet, Writer out )        throws IOException    {        // First, validate our input.        if ( null == packet ) {            throw new IllegalArgumentException( "The packet is null." );        }        if ( null == out ) {            throw new IllegalArgumentException( "The writer is null." );        }        // Encode the packet object to the stream.        out.write( "<packet type=\"" );        out.write( Integer.toString(packet.getCommand()) );        out.write( "\" >" );        // Is the packet zipped?        //boolean zipped = packet.isZipped();        boolean zipped = false;        // Do we have any data in this packet?        // N.B. this action will unzip the packet.        Object[] data = packet.getData();        if ( null != data ) {            // Should we compress the data?            if ( zipped ) {                // XML encode the data and GZIP it.                ByteArrayOutputStream baos = new ByteArrayOutputStream();                Writer zipOut = new BufferedWriter                    ( new OutputStreamWriter                      ( new GZIPOutputStream(baos) )                      );                PacketEncoder.encodeData( packet, zipOut );                zipOut.close();                // Base64 encode the commpressed data.                // Please note, I couldn't get anything other than a                // straight stream-to-stream encoding to work.                byte[] zipData = baos.toByteArray();                ByteArrayOutputStream base64 = new ByteArrayOutputStream                    ( (4*zipData.length+2)/3 );                Base64.encode( new ByteArrayInputStream(zipData), base64, false );                /* begin debug code **                   int loop;                   for ( loop = 0; loop < zipData.length; loop++ ) {                   System.out.print( (char) zipData[loop] );                   }                   System.out.println( "" );                   String zipStr = baos.toString();                   for ( loop = 0; loop < zipStr.length(); loop++ ) {                   System.out.print( zipStr.charAt(loop) );                   }                   System.out.println( "" );                   zipStr = base64.toString();                   for ( loop = 0; loop < zipStr.length(); loop++ ) {                   System.out.print( zipStr.charAt(loop) );                   }                   System.out.println( "" );                   **  end  debug code */                // Save the compressed data as the packetData CDATA.                out.write( "<packetData count=\"" );                out.write( Integer.toString(data.length) );                out.write( "\" isGzipped=\"true\" >" );                out.write( base64.toString() );                out.write( "</packetData>" );            } // End packet-is-zipped            else {                // Don't compress the XML.                out.write( "<packetData count=\"" );                out.write( Integer.toString(data.length) );                out.write( "\" isGzipped=\"false\" >" );                PacketEncoder.encodeData( packet, out );                out.write( "</packetData>" );            }        } // End have-data        // Finish off the packet.        out.write( "</packet>" );    }    /**     * Decode a <code>Packet</code> object from the passed node.     *     * @param   node - the <code>ParsedXML</code> node for this object.     *          This value must not be <code>null</code>.     * @param   game - the <code>IGame</code> the decoded object belongs to.     * @return  the <code>Packet</code> object based on the node.     * @throws  <code>IllegalArgumentException</code> if the node is     *          <code>null</code>.     * @throws  <code>IllegalStateException</code> if the node does not     *          contain a valid <code>Packet</code>.     * @throws  <code>NumberFormatException</code> if the value of a numeric     *          data element is not in a valid format.     */    public static Packet decode( ParsedXML node, IGame game ) {        Packet packet = null;        int command = 0;        Object[] data = null;        // Make sure we got a valid packet.        if ( null == node ) {            throw new IllegalArgumentException( "The passed node is null." );        }        if ( !node.getName().equals("packet") ) {            throw new IllegalStateException                ( "The passed node is not for a packet." );        }        // Figure out what type of packet this is.        String commandStr = node.getAttribute( "type" );        if ( null == commandStr ) {            throw new IllegalStateException                ( "Could not determine the packet type." );        }        command = Integer.parseInt( commandStr );        // TODO : perform version checking.        // Walk the packet node's children.  Try to find a "packetData" node.        Enumeration children = node.elements();        while ( children.hasMoreElements() ) {            ParsedXML subNode = (ParsedXML) children.nextElement();            if ( subNode.getName().equals("packetData") ) {                // How many data elements are in the packet data?                final int count = Integer.parseInt                    ( subNode.getAttribute("count") );                data = new Object[count];                // Do we need to unzip the data elements?                Enumeration dataElements = null;                if ( subNode.getAttribute("isGzipped").equals("true") ) {                    // Try to find the zipped content.                    String cdata = subNode.getContent();                    if ( null == cdata ) {                        Enumeration cdataEnum = subNode.elements();                        while ( cdataEnum.hasMoreElements() &&                                null == cdata ) {                            final ParsedXML cdataNode =                                (ParsedXML) cdataEnum.nextElement();                            if ( cdataNode.getTypeName().equals("text") ) {                                cdata = cdataNode.getContent();                            }                            else if ( cdataNode.getTypeName().equals("cdata") ){                                cdata = cdataNode.getContent();                            }                        }                    } // End look-for-cdata-nodes                    // Did we find the zipped content?                    if ( null == cdata ) {                        throw new IllegalStateException                            ( "Could not find CDATA for packetData." );                    }                    // Yup.  Unencode the data from Base64.                    byte[] unBase64 = Base64.decodeToBytes( cdata );                    InputStream parseStream;                    try {                        // Unzip the data.                        parseStream = new GZIPInputStream                            ( new ByteArrayInputStream(unBase64) );                    }                    catch ( IOException ioErr ) {                        StringBuffer iobuf = new StringBuffer();                        iobuf.append( "Could not unzip data elements: " )                            .append( ioErr.getMessage() );                        throw new IllegalStateException( iobuf.toString() );                    }                    try {                        /* BEGIN debug code **                        try {                            parseStream.mark(64000);                            int inChar = 0;                            while ( -1 != (inChar = parseStream.read()) ) {                                System.out.print( (char) inChar );                            }                            System.out.println( "" );                            parseStream.reset();                        }                        catch ( IOException debugErr ) {                            debugErr.printStackTrace();                        }                        **  END  debug code */                                                // Parse the XML.                        ParsedXML dummyNode = TinyParser.parseXML(parseStream);                        dataElements = dummyNode.elements();                    }                    catch ( ParseException parseErr ) {                        StringBuffer parsebuf = new StringBuffer();                        parsebuf.append( "Could not parse data elements: " )                            .append( parseErr.getMessage() );                        throw new IllegalStateException( parsebuf.toString() );                    }                }                else {                    // Nope.  Just return the data elements.                    dataElements = subNode.elements();                }                // Walk the children, and decode them into the data array.                for ( int loop = 0; dataElements.hasMoreElements(); loop++ ) {                    data[loop] = PacketEncoder.decodeData                        ( (ParsedXML) dataElements.nextElement(), game );                }            } // End found-packetData-element        } // Check the next child of the packet node.        // Create and return the packet.        if ( null != data ) {            packet = new Packet( command, data );        }        else {            packet = new Packet( command );        }        return packet;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -