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