All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.redis.session.transcoders.BaseSerializingTranscoder Maven / Gradle / Ivy

There is a newer version: 9.4.36.2
Show newest version
// copied from https://github.com/killme2008/xmemcached/tree/90dd456f29/src/main/java/net/rubyeye/xmemcached/transcoders
package org.eclipse.jetty.redis.session.transcoders;

import java.io.*;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.InflaterInputStream;

import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/**
 * Base class for any transcoders that may want to work with serialized or
 * compressed data.
 */
public abstract class BaseSerializingTranscoder {

    /**
     * Default compression threshold value.
     */
    public static final int DEFAULT_COMPRESSION_THRESHOLD = 16384;

    public static final String DEFAULT_CHARSET = "UTF-8";

    protected int compressionThreshold = DEFAULT_COMPRESSION_THRESHOLD;
    protected String charset = DEFAULT_CHARSET;
    protected CompressionMode compressMode = CompressionMode.GZIP;
    protected static final Logger log = Log.getLogger(BaseSerializingTranscoder.class);

    /**
     * Set the compression threshold to the given number of bytes. This
     * transcoder will attempt to compress any data being stored that's larger
     * than this.
     *
     * @param to the number of bytes
     */
    public void setCompressionThreshold(int to) {
        this.compressionThreshold = to;
    }

    public CompressionMode getCompressMode() {
        return compressMode;
    }

    public void setCompressionMode(CompressionMode compressMode) {
        this.compressMode = compressMode;
    }

    /**
     * Set the character set for string value transcoding (defaults to UTF-8).
     */
    public void setCharset(String to) {
        // Validate the character set.
        try {
            new String(new byte[97], to);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        this.charset = to;
    }

    /**
     * Get the bytes representing the given serialized object.
     */
    protected byte[] serialize(Object o) {
        if (o == null) {
            throw new NullPointerException("Can't serialize null");
        }
        byte[] rv = null;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream(bos);
            os.writeObject(o);
            os.close();
            bos.close();
            rv = bos.toByteArray();
        } catch (IOException e) {
            throw new IllegalArgumentException("Non-serializable object", e);
        }
        return rv;
    }

    /**
     * Get the object represented by the given serialized bytes.
     */
    protected Object deserialize(byte[] in) {
        Object rv = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream is = null;
        try {
            if (in != null) {
                bis = new ByteArrayInputStream(in);
                is = new ClassLoadingObjectInputStream(bis);
                rv = is.readObject();

            }
        } catch (IOException e) {
            log.warn("Caught IOException decoding {} bytes of data", in.length, e);
        } catch (ClassNotFoundException e) {
            log.warn("Caught CNFE decoding {} bytes of data", in.length, e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // ignore
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return rv;
    }

    /**
     * Compress the given array of bytes.
     */
    public final byte[] compress(byte[] in) {
        switch (this.compressMode) {
            case GZIP:
                return gzipCompress(in);
            case ZIP:
                return zipCompress(in);
            default:
                return gzipCompress(in);
        }

    }

    private byte[] zipCompress(byte[] in) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(in.length);
        DeflaterOutputStream os = new DeflaterOutputStream(baos);
        try {
            os.write(in);
            os.finish();
            try {
                os.close();
            } catch (IOException e) {
                log.warn("Close DeflaterOutputStream error", e);
            }
        } catch (IOException e) {
            throw new RuntimeException("IO exception compressing data", e);
        } finally {
            try {
                baos.close();
            } catch (IOException e) {
                log.warn("Close ByteArrayOutputStream error", e);
            }
        }
        return baos.toByteArray();
    }

    private static byte[] gzipCompress(byte[] in) {
        if (in == null) {
            throw new NullPointerException("Can't compress null");
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        GZIPOutputStream gz = null;
        try {
            gz = new GZIPOutputStream(bos);
            gz.write(in);
        } catch (IOException e) {
            throw new RuntimeException("IO exception compressing data", e);
        } finally {
            if (gz != null) {
                try {
                    gz.close();
                } catch (IOException e) {
                    log.warn("Close GZIPOutputStream error", e);
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    log.warn("Close ByteArrayOutputStream error", e);
                }
            }
        }
        byte[] rv = bos.toByteArray();
        // log.debug("Compressed %d bytes to %d", in.length, rv.length);
        return rv;
    }

    static int COMPRESS_RATIO = 8;

    /**
     * Decompress the given array of bytes.
     *
     * @return null if the bytes cannot be decompressed
     */
    protected byte[] decompress(byte[] in) {
        switch (this.compressMode) {
            case GZIP:
                return gzipDecompress(in);
            case ZIP:
                return zipDecompress(in);
            default:
                return gzipDecompress(in);
        }
    }

    private byte[] zipDecompress(byte[] in) {
        int size = in.length * COMPRESS_RATIO;
        ByteArrayInputStream bais = new ByteArrayInputStream(in);
        InflaterInputStream is = new InflaterInputStream(bais);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
        try {
            byte[] uncompressMessage = new byte[size];
            while (true) {
                int len = is.read(uncompressMessage);
                if (len <= 0) {
                    break;
                }
                baos.write(uncompressMessage, 0, len);
            }
            baos.flush();
            return baos.toByteArray();

        } catch (IOException e) {
            log.warn("Failed to decompress data", e);
            // baos = null;
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                log.warn("failed to close InflaterInputStream");
            }
            try {
                bais.close();
            } catch (IOException e) {
                log.warn("failed to close ByteArrayInputStream");
            }
            try {
                baos.close();
            } catch (IOException e) {
                log.warn("failed to close ByteArrayOutputStream");
            }
        }
        return baos == null ? null : baos.toByteArray();
    }

    private byte[] gzipDecompress(byte[] in) {
        ByteArrayOutputStream bos = null;
        if (in != null) {
            ByteArrayInputStream bis = new ByteArrayInputStream(in);
            bos = new ByteArrayOutputStream();
            GZIPInputStream gis = null;
            try {
                gis = new GZIPInputStream(bis);

                byte[] buf = new byte[64 * 1024];
                int r = -1;
                while ((r = gis.read(buf)) > 0) {
                    bos.write(buf, 0, r);
                }
            } catch (IOException e) {
                log.warn("Failed to decompress data", e);
                bos = null;
            } finally {
                if (gis != null) {
                    try {
                        gis.close();
                    } catch (IOException e) {
                        log.warn("Close GZIPInputStream error", e);
                    }
                }
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        log.warn("Close ByteArrayInputStream error", e);
                    }
                }
            }
        }
        return bos == null ? null : bos.toByteArray();
    }

    /**
     * Decode the string with the current character set.
     */
    protected String decodeString(byte[] data) {
        String rv = null;
        try {
            if (data != null) {
                rv = new String(data, this.charset);
            }
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return rv;
    }

    /**
     * Encode a string into the current character set.
     */
    protected byte[] encodeString(String in) {
        byte[] rv = null;
        try {
            rv = in.getBytes(this.charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return rv;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy