169N/A/*
2362N/A * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A */
0N/A
0N/Aimport java.io.*;
0N/Aimport java.rmi.server.*;
0N/Aimport java.net.*;
0N/A
0N/Apublic class Compress {
0N/A
0N/A interface CompressConstants {
169N/A // constants for 6-bit code values
169N/A static final int NOP = 0; // no operation: used to pad words on flush()
169N/A static final int RAW = 1; // introduces raw byte format
169N/A static final int BASE = 2; // base for codes found in lookup table
169N/A static final String codeTable =
169N/A "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ,.!?\"'()";
0N/A }
169N/A
169N/A public static class CompressRMIClientSocketFactory
169N/A implements java.rmi.server.RMIClientSocketFactory, Serializable {
0N/A
169N/A public Socket createSocket(String host, int port)
169N/A throws IOException {
169N/A
169N/A return ((Socket) new CompressSocket(host, port));
169N/A }
0N/A }
0N/A
169N/A public static class CompressRMIServerSocketFactory
169N/A implements RMIServerSocketFactory,
169N/A Serializable {
0N/A
169N/A public ServerSocket createServerSocket(int port)
169N/A throws IOException {
169N/A
169N/A return ((ServerSocket) new CompressServerSocket(port));
169N/A }
0N/A }
169N/A
0N/A public static class CompressSocket extends Socket {
169N/A private InputStream in;
169N/A private OutputStream out;
169N/A public CompressSocket() { super(); }
169N/A public CompressSocket(String host, int port) throws IOException {
169N/A super(host, port);
0N/A }
169N/A public InputStream getInputStream() throws IOException {
169N/A if (in == null) {
169N/A in = new CompressInputStream(super.getInputStream());
169N/A }
169N/A return in;
169N/A }
169N/A public OutputStream getOutputStream() throws IOException {
169N/A if (out == null) {
169N/A out = new CompressOutputStream(super.getOutputStream());
169N/A }
169N/A return out;
169N/A }
0N/A }
0N/A
0N/A public static class CompressServerSocket extends ServerSocket {
169N/A public CompressServerSocket(int port) throws IOException {
169N/A super(port);
169N/A }
169N/A public Socket accept() throws IOException {
169N/A Socket s = new CompressSocket();
169N/A implAccept(s);
169N/A return s;
169N/A }
0N/A }
0N/A
0N/A public static class CompressInputStream extends FilterInputStream
169N/A implements CompressConstants
0N/A {
169N/A
169N/A public CompressInputStream(InputStream in) {
169N/A super(in);
169N/A }
169N/A
169N/A // buffer of unpacked 6-bit codes from last 32-word read
169N/A int buf[] = new int[5];
169N/A
169N/A // position of next code to read in buffer (5 == end of buffer)
169N/A int bufPos = 5;
169N/A
169N/A public int read() throws IOException {
169N/A try {
169N/A int code;
169N/A do {
169N/A code = readCode();
169N/A } while (code == NOP); // ignore NOP codes
169N/A
169N/A if (code >= BASE)
169N/A return codeTable.charAt(code - BASE);
169N/A else if (code == RAW) {
169N/A int high = readCode();
169N/A int low = readCode();
169N/A return (high << 4) | low;
169N/A } else
169N/A throw new IOException("unknown compression code: " + code);
169N/A } catch (EOFException e) {
169N/A return -1;
169N/A }
169N/A }
169N/A
169N/A public int read(byte b[], int off, int len) throws IOException {
169N/A if (len <= 0) {
169N/A return 0;
169N/A }
169N/A
169N/A int c = read();
169N/A if (c == -1) {
169N/A return -1;
169N/A }
169N/A b[off] = (byte)c;
169N/A
169N/A int i = 1;
169N/A /*****
169N/A try {
169N/A for (; i < len ; i++) {
169N/A c = read();
169N/A if (c == -1) {
169N/A break;
169N/A }
169N/A if (b != null) {
169N/A b[off + i] = (byte)c;
169N/A }
169N/A }
169N/A } catch (IOException ee) {
169N/A }
169N/A *****/
169N/A return i;
169N/A }
169N/A
169N/A private int readCode() throws IOException {
169N/A if (bufPos == 5) {
169N/A int b1 = in.read();
169N/A int b2 = in.read();
169N/A int b3 = in.read();
169N/A int b4 = in.read();
169N/A if ((b1 | b2 | b3 | b4) < 0)
169N/A throw new EOFException();
169N/A int pack = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
169N/A buf[0] = (pack >>> 24) & 0x3F;
169N/A buf[1] = (pack >>> 18) & 0x3F;
169N/A buf[2] = (pack >>> 12) & 0x3F;
169N/A buf[3] = (pack >>> 6) & 0x3F;
169N/A buf[4] = (pack >>> 0) & 0x3F;
169N/A bufPos = 0;
169N/A }
169N/A return buf[bufPos++];
169N/A }
0N/A }
0N/A
0N/A public static class CompressOutputStream extends FilterOutputStream
169N/A implements CompressConstants
0N/A {
169N/A
169N/A public CompressOutputStream(OutputStream out) {
169N/A super(out);
169N/A }
169N/A
169N/A // buffer of 6-bit codes to pack into next 32-bit word
169N/A int buf[] = new int[5];
169N/A
169N/A // number of valid codes pending in buffer
169N/A int bufPos = 0;
169N/A
169N/A public void write(int b) throws IOException {
169N/A b &= 0xFF; // force argument to a byte
169N/A
169N/A int pos = codeTable.indexOf((char)b);
169N/A if (pos != -1)
169N/A writeCode(BASE + pos);
169N/A else {
169N/A writeCode(RAW);
169N/A writeCode(b >> 4);
169N/A writeCode(b & 0xF);
169N/A }
169N/A }
169N/A
169N/A public void write(byte b[], int off, int len) throws IOException {
169N/A /*
169N/A * This is quite an inefficient implementation, because it has to
169N/A * call the other write method for every byte in the array. It
169N/A * could be optimized for performance by doing all the processing
169N/A * in this method.
169N/A */
169N/A for (int i = 0; i < len; i++)
169N/A write(b[off + i]);
169N/A }
169N/A
169N/A public void flush() throws IOException {
169N/A while (bufPos > 0)
169N/A writeCode(NOP);
169N/A }
169N/A
169N/A private void writeCode(int c) throws IOException {
169N/A buf[bufPos++] = c;
169N/A if (bufPos == 5) { // write next word when we have 5 codes
169N/A int pack = (buf[0] << 24) | (buf[1] << 18) | (buf[2] << 12) |
169N/A (buf[3] << 6) | buf[4];
169N/A out.write((pack >>> 24) & 0xFF);
169N/A out.write((pack >>> 16) & 0xFF);
169N/A out.write((pack >>> 8) & 0xFF);
169N/A out.write((pack >>> 0) & 0xFF);
169N/A bufPos = 0;
169N/A }
169N/A }
0N/A }
0N/A}