package com.appmetr.hercules.utils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import java.io.*; import java.util.Collection; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class SerializationUtils { private static final int UTF_FLAG_NULL = 0; private static final int UTF_FLAG_OLD_STRING = 1; private static final int UTF_FLAG_BYTES = 2; public static <T extends Serializable> byte[] serialize(T obj) { try { ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); ObjectOutput out = null; try { out = new ObjectOutputStream(baos); out.writeObject(obj); out.flush(); } finally { if (out != null) { try { out.close(); } catch (Exception e) { /* NOP */ } } } baos.flush(); return baos.toByteArray(); } finally { if (baos != null) { try { baos.close(); } catch (Exception e) { /* NOP */ } } } } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Serializable> T deserialize(byte[] buf) { try { ByteArrayInputStream bis = null; try { bis = new ByteArrayInputStream(buf); ObjectInputStream oin = null; try { oin = new ObjectInputStream(bis); return (T) oin.readObject(); } finally { if (oin != null) { try { oin.close(); } catch (IOException e) { /* NOP */ } } } } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { /* NOP */ } } } } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Externalizable> byte[] serialize(T obj) { try { return serializeSafe(obj); } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Externalizable> void deserialize(byte[] buf, T obj) { try { deserializeSafe(buf, obj); } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Externalizable> byte[] serializeGZip(T obj) { try { return serializeGZipSafe(obj); } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Externalizable> void deserializeGZip(byte[] buf, T obj) { try { deserializeGZipSafe(buf, obj); } catch (Exception e) { throw new RuntimeException(e); } } public static <T extends Externalizable> byte[] serializeSafe(T obj) throws IOException, ClassNotFoundException { ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); ObjectOutput out = null; try { out = new ObjectOutputStream(baos); obj.writeExternal(out); out.flush(); } finally { if (out != null) { try { out.close(); } catch (Exception e) { /* NOP */ } } } baos.flush(); return baos.toByteArray(); } finally { if (baos != null) { try { baos.close(); } catch (Exception e) { /* NOP */ } } } } public static <T extends Externalizable> void deserializeSafe(byte[] buf, T obj) throws IOException, ClassNotFoundException { ByteArrayInputStream bis = null; try { bis = new ByteArrayInputStream(buf); ObjectInputStream oin = null; try { oin = new ObjectInputStream(bis); obj.readExternal(oin); } finally { if (oin != null) { try { oin.close(); } catch (IOException e) { /* NOP */ } } } } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { /* NOP */ } } } } public static <T extends Externalizable> byte[] serializeGZipSafe(T obj) throws IOException, ClassNotFoundException { ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); GZIPOutputStream gzip = null; try { gzip = new GZIPOutputStream(baos); ObjectOutput out = null; try { out = new ObjectOutputStream(gzip); obj.writeExternal(out); out.flush(); } finally { if (out != null) { try { out.close(); } catch (Exception e) { /* NOP */ } } } gzip.finish(); gzip.flush(); } finally { if (gzip != null) { try { gzip.close(); } catch (Exception e) { /* NOP */ } } } baos.flush(); return baos.toByteArray(); } finally { if (baos != null) { try { baos.close(); } catch (Exception e) { /* NOP */ } } } } public static <T extends Externalizable> void deserializeGZipSafe(byte[] buf, T obj) throws IOException, ClassNotFoundException { ByteArrayInputStream bis = null; try { bis = new ByteArrayInputStream(buf); GZIPInputStream gzip = null; try { gzip = new GZIPInputStream(bis); ObjectInputStream oin = null; try { oin = new ObjectInputStream(gzip); obj.readExternal(oin); } finally { if (oin != null) { try { oin.close(); } catch (IOException e) { /* NOP */ } } } } finally { if (gzip != null) { try { gzip.close(); } catch (IOException e) { /* NOP */ } } } } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { /* NOP */ } } } } public static void writeNullUTF(DataOutput out, String s) throws IOException { if (s == null) { out.writeInt(UTF_FLAG_NULL); return; } byte[] buf = s.getBytes("UTF-8"); writeNullBytes(out, buf); } public static void writeNullBytes(DataOutput out, byte[] buf) throws IOException { if (buf == null) { out.writeInt(UTF_FLAG_NULL); } else { out.writeInt(UTF_FLAG_BYTES); out.writeInt(buf.length); out.write(buf); } } public static int calcNullUTFSerializedSize(String s) { try { if (s == null) { return 4; } else { return 4 + s.getBytes("UTF-8").length + 4; } } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } public static byte[] readNullBytes(DataInput in) throws IOException { int flag = in.readInt(); if (flag == UTF_FLAG_NULL) { return null; } else if (flag == UTF_FLAG_BYTES) { int bufLength = in.readInt(); byte[] buf = new byte[bufLength]; in.readFully(buf); return buf; } else { throw new IOException("Read UTF - invalid flag: " + flag); } } public static String readNullUTF(DataInput in) throws IOException { int flag = in.readInt(); if (flag == UTF_FLAG_NULL) { return null; } else if (flag == UTF_FLAG_OLD_STRING) { return in.readUTF(); } else if (flag == UTF_FLAG_BYTES) { int bufLength = in.readInt(); byte[] buf = new byte[bufLength]; in.readFully(buf); return new String(buf, "UTF-8"); } else { throw new IOException("Read UTF - invalid flag: " + flag); } } public static void writeCollectionString(DataOutput out, Collection<String> list) throws IOException { out.writeInt(list.size()); for (String item : list) { SerializationUtils.writeNullUTF(out, item); } } public static void readCollectionString(DataInput in, Collection<String> buffer) throws IOException { int size = in.readInt(); for (int i = 0; i < size; i++) { buffer.add(SerializationUtils.readNullUTF(in)); } } //Null safe java object serialization public static void writeNullSafeBoolean(DataOutput out, Boolean value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeBoolean(value); } } public static Boolean readNullSafeBoolean(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readBoolean(); } return null; } public static void writeNullSafeShort(DataOutput out, Short value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeShort(value); } } public static Short readNullSafeShort(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readShort(); } return null; } public static void writeNullSafeInt(DataOutput out, Integer value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeInt(value); } } public static Integer readNullSafeInt(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readInt(); } return null; } public static void writeNullSafeLong(DataOutput out, Long value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeLong(value); } } public static Long readNullSafeLong(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readLong(); } return null; } public static void writeNullSafeDateTime(DataOutput out, DateTime date) throws IOException { boolean isNull = date == null; out.writeBoolean(isNull); if (!isNull) { out.writeLong(date.getMillis()); writeNullUTF(out, date.getZone().getID()); } } public static DateTime readNullSafeDateTime(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { long millis = in.readLong(); String tzId = readNullUTF(in); return new DateTime(millis, DateTimeZone.forID(tzId)); } return null; } public static void writeNullSafeFloat(DataOutput out, Float value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeFloat(value); } } public static Float readNullSafeFloat(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readFloat(); } return null; } public static void writeNullSafeDouble(DataOutput out, Double value) throws IOException { boolean isNull = value == null; out.writeBoolean(isNull); if (!isNull) { out.writeDouble(value); } } public static Double readNullSafeDouble(DataInput in) throws IOException { boolean isNull = in.readBoolean(); if (!isNull) { return in.readDouble(); } return null; } public static boolean isGZipStream(byte[] bytes) { int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); return (GZIPInputStream.GZIP_MAGIC == head); } }