package eu.siacs.conversations.utils.zlib; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.NoSuchAlgorithmException; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; /** *

* Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this * Implementation, preferable via reflection. The @hide was remove in API level * 19. This class might thus go away in the future. *

*

* Please use {@link ZLibOutputStream#SUPPORTED} to check for flush * compatibility. *

*/ public class ZLibOutputStream extends DeflaterOutputStream { /** * The reflection based flush method. */ private final static Method method; /** * SUPPORTED is true if a flush compatible method exists. */ public final static boolean SUPPORTED; /** * Static block to initialize {@link #SUPPORTED} and {@link #method}. */ static { Method m = null; try { m = Deflater.class.getMethod("deflate", byte[].class, int.class, int.class, int.class); } catch (SecurityException e) { } catch (NoSuchMethodException e) { } method = m; SUPPORTED = (method != null); } /** * Create a new ZLib compatible output stream wrapping the given low level * stream. ZLib compatiblity means we will send a zlib header. * * @param os * OutputStream The underlying stream. * @throws IOException * In case of a lowlevel transfer problem. * @throws NoSuchAlgorithmException * In case of a {@link Deflater} error. */ public ZLibOutputStream(OutputStream os) throws IOException, NoSuchAlgorithmException { super(os, new Deflater(Deflater.BEST_COMPRESSION)); } /** * Flush the given stream, preferring Java7 FLUSH_SYNC if available. * * @throws IOException * In case of a lowlevel exception. */ @Override public void flush() throws IOException { if (!SUPPORTED) { super.flush(); return; } try { int count = 0; do { count = (Integer) method.invoke(def, buf, 0, buf.length, 3); if (count > 0) { out.write(buf, 0, count); } } while (count > 0); } catch (IllegalArgumentException e) { throw new IOException("Can't flush"); } catch (IllegalAccessException e) { throw new IOException("Can't flush"); } catch (InvocationTargetException e) { throw new IOException("Can't flush"); } super.flush(); } }