ZLibOutputStream.java

 1package eu.siacs.conversations.utils.zlib;
 2
 3import java.io.IOException;
 4import java.io.OutputStream;
 5import java.lang.reflect.InvocationTargetException;
 6import java.lang.reflect.Method;
 7import java.security.NoSuchAlgorithmException;
 8import java.util.zip.Deflater;
 9import java.util.zip.DeflaterOutputStream;
10
11/**
12 * <p>Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this
13 * Implementation, preferable via reflection. The @hide was remove in API level
14 * 19. This class might thus go away in the future.</p>
15 * <p>Please use {@link ZLibOutputStream#SUPPORTED} to check for flush
16 * compatibility.</p> 
17 */
18public class ZLibOutputStream extends DeflaterOutputStream {
19
20    /**
21     * The reflection based flush method.
22     */
23
24    private final static Method method;
25    /**
26     * SUPPORTED is true if a flush compatible method exists.
27     */
28    public final static boolean SUPPORTED;
29
30    /**
31     * Static block to initialize {@link #SUPPORTED} and {@link #method}.
32     */
33    static {
34        Method m = null;
35        try {
36            m = Deflater.class.getMethod("deflate", byte[].class, int.class, int.class, int.class);
37        } catch (SecurityException e) {
38        } catch (NoSuchMethodException e) {
39        }
40        method = m;
41        SUPPORTED = (method != null);
42    }
43
44    /**
45     * Create a new ZLib compatible output stream wrapping the given low level
46     * stream. ZLib compatiblity means we will send a zlib header. 
47     * @param os OutputStream The underlying stream.
48     * @throws IOException In case of a lowlevel transfer problem.
49     * @throws NoSuchAlgorithmException In case of a {@link Deflater} error.
50     */
51    public ZLibOutputStream(OutputStream os) throws IOException,
52            NoSuchAlgorithmException {
53        super(os, new Deflater(Deflater.BEST_COMPRESSION));
54    }
55
56    /**
57     * Flush the given stream, preferring Java7 FLUSH_SYNC if available.
58     * @throws IOException In case of a lowlevel exception.
59     */
60    @Override
61    public void flush() throws IOException {
62        if (!SUPPORTED) {
63            super.flush();
64            return;
65        }
66        try {
67	    int count = 0;
68            do {
69                count = (Integer) method.invoke(def, buf, 0, buf.length, 3);
70		if (count > 0) {
71                    out.write(buf, 0, count);
72		}
73            } while (count > 0);
74        } catch (IllegalArgumentException e) {
75            throw new IOException("Can't flush");
76        } catch (IllegalAccessException e) {
77            throw new IOException("Can't flush");
78        } catch (InvocationTargetException e) {
79            throw new IOException("Can't flush");
80        }
81        super.flush();
82    }
83
84}