📄 connectioncompressed.java
字号:
package mujmail.connections;/*MujMail - Simple mail client for J2MECopyright (C) 2006 Nguyen Son Tung <n.sontung@gmail.com>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */import java.io.*;import javax.microedition.io.*;import mujmail.Lang;import mujmail.MyException;/** * Implements ConnectionInterface that compress data. (Compression filter) * Now using RLE "compression". * No output buffering, no flush. * InOut is line oriented */ public class ConnectionCompressed implements ConnectionInterface { /** Flag signals if we want to print debug prints */ private static final boolean DEBUG = false; /** Connection to sending compressed data */ private ConnectorInterface connector = null; /** Indicates whether is connection open or close */ private boolean connected = false; private boolean quit = false; /** String that identify compression type. * Note: Pointer to one of predefined constants, no content comparison */ private String compression = COMPRESSION_TYPE_NONE; // None have to be default /** Compression type identification constants */ /** No compression is used for communication. */ public static final String COMPRESSION_TYPE_NONE = "NONE"; //#ifdef MUJMAIL_COMPRESSED_CONNECTION /** Communication with server is compressed by RLE compression. */ public static final String COMPRESSION_TYPE_RLE = "RLE"; /** Communication from server is compressed by GZIP compression. */ public static final String COMPRESSION_TYPE_GZIP = "GZIP"; /** Communication initialization constants */ private static final String INIT_HELLO = "Xmujmail-compression"; private static final String INIT_VERSION = "0.5"; //#endif /** Counts changes of compression type */ private static int counter = 0; /** Count send data. Data incoming from higher level into send method */ private int dataSendIn = 0; /** Count read data. Data gets to higher level from getLine method */ private int dataReadIn = 0; private static final int BUFFER_LEN = 256; /** Buffer for outgoing compression data */ private InOutBuffer buff = null; private Object syncIn = new Object(); private Object syncOut = new Object(); /** Last that was take back */ private StringBuffer lastLine = new StringBuffer(); /** Mark whether we want to get the last line back or new data from buffer */ private boolean backMark; /*** RLE Compression specifies stuff */ // Hold state of RLE from last stop private char RLE_Char; private int RLE_Count = 0; // How many times put into output /** Creates new socket connection. * <p>{@link mujmail.connections.ConnectorSocket} are used for communication. * <p>No compression is set at first. */ public ConnectionCompressed() { connector = new ConnectorSocket(); buff = new InOutBuffer( BUFFER_LEN, connector); } /** * Construct connection proxy * @param _connector Connector used for data delivery. * If null standard ConnectorSocket will be used. * @param _compression Initial type of compression * */ public ConnectionCompressed(ConnectorInterface _connector, String _compression) { if (_connector != null) connector = _connector; else connector = new ConnectorSocket(); compression = _compression; buff = new InOutBuffer( BUFFER_LEN, connector); } public synchronized void close() { connected = false; buff.InSkipBuffer(); // Flushing buffer try { if (connector != null) connector.close(); } catch (IOException ex) { // Connection closing problem, let is connection closed by timeout } } public synchronized void open(String url, boolean ssl, byte sslType) throws MyException { if (connector == null) return; compression = COMPRESSION_TYPE_NONE; try { connector.open(url, ssl, sslType); } catch (ConnectionNotFoundException ex) { ex.printStackTrace(); throw new MyException(MyException.COM_UNKNOWN, Lang.get( Lang.EXP_COM_UNKNOWN) + " Server not found." + ex.getMessage()); // Try to open invalid location } catch (EOFException ex) { ex.printStackTrace(); throw new MyException(MyException.COM_HALTED); } catch (IOException ex) { //System.out.println(ex.getMessage()); //ex.printStackTrace(); ex.printStackTrace(); throw new MyException(MyException.COM_HALTED, ex); } connected = true; } //#ifdef MUJMAIL_COMPRESSED_CONNECTION /** * Sets new compression type * * @param newCompression Compression type to uses. * It have to be one from predefined strings in class. * Test is done string addressed (not content) * <p> * Note: Checks if server counter support compression. Sends data into output. */ public void changeCompression(String newCompression) throws MyException { if (connector == null) return; // Check if newCompression is supported // Note not comparing strings but addresses if ( (newCompression != COMPRESSION_TYPE_NONE) && (newCompression != COMPRESSION_TYPE_RLE) && (newCompression != COMPRESSION_TYPE_GZIP) ) { return; } // GZIP compression cann't be changed unsupported if ( (compression == COMPRESSION_TYPE_GZIP) && (newCompression != COMPRESSION_TYPE_GZIP) ) { return; } // Place for preinitialization // Setting compression String tag = "compress" + counter++ + " "; String command = tag + INIT_HELLO + " " + INIT_VERSION + " " + newCompression; // Add necessary compression type initialization informations if needed String result = null; String oldCompression = compression; try { sendCRLF(command); result = getLine(); // Last line in old compression while (!result.startsWith(tag)) { //multiline response result = getLine(); } result = result.substring(tag.length()); if (result.startsWith("OK")) { // All correct - set parameters compression = newCompression; // This have to be set here, to connector.flush works correctly if (compression == COMPRESSION_TYPE_GZIP) { connector = new ConnectorGZip(connector, buff); buff.changeConnector(connector); connector.flush(); } getLine(); // To read server reply "* compression OK" } } catch ( IOException ex) { // We need close connection immediately, // because each side tries to use different compression compression = oldCompression; throw new MyException( MyException.COM_UNKNOWN, ex); } } //#endif public void sendCRLF(String command) throws MyException { send((command + CRLF).getBytes()); } /** * Send line (or multiline) to server. * @param command The line to be written. * @throws MyException If connection is closed or transmission error */ public void send(String command) throws MyException { send(command.getBytes()); } /** * Buffer to server. * @param command bytes to be sent * @throws MyException if connection is closed or transmission error * Note: Have to be synchronized ... share one instance of output buffer */ public void send(byte[] command) throws MyException { if (connector == null ) return; if (command == null || command.length == 0) return; if (quit) { throw new MyException(MyException.COM_HALTED); } synchronized (syncIn) { // Counting send (uncompressed)data dataSendIn += command.length; //#ifdef MUJMAIL_COMPRESSED_CONNECTION if (compression == COMPRESSION_TYPE_RLE) { try { byte prevByte = command[0]; int inBufPos = 1; // Position in input buffer -- command int prevByteCount = 1; while (inBufPos < command.length) { if (command[inBufPos] == prevByte) { // Same character as before inBufPos++; prevByteCount++; // Test if length of same char in not too long if (prevByteCount == 18) { // To many same character, put out sequence buff.OutAddByte((byte)(0xFF)); // Writes 17times same char buff.OutAddByte(prevByte); prevByteCount = 1; } } else { // Different character in the input --> write current run if ((command[inBufPos] & 0xF0) == 0xF0 || prevByteCount > 1) { // Longer run or problematic char --> double char code buff.OutAddByte((byte)(0xF0 + prevByteCount - 1)); buff.OutAddByte(prevByte); } else { // Single non problematic char (not binary 1111????) -> one byte code buff.OutAddByte(prevByte); } // Read next char from input prevByte = command[inBufPos]; prevByteCount = 1; inBufPos++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -