/* Serializables.java Purpose: Description: History: Sun Jun 25 22:54:45 2006, Created by tomyeh Copyright (C) 2006 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.io; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utilities to handle java.io.Serializable. * * @author tomyeh */ public class Serializables { /** The logger called org.zkoss.io.serializable used to log serialization * information. You could set it to DEBUG, such that the non-serializable * and ignored values will be logged. * @since 5.0.7 */ public static final Logger logio = LoggerFactory.getLogger("org.zkoss.io.serializable"); private Serializables() {} /** Writes only serializable entries of the specified map. * Non-serializable attributes are ignored. */ public static <K, V> void smartWrite(ObjectOutputStream s, Map<K, V> map) throws IOException { if (map != null) { final boolean debug = logio.isDebugEnabled(); for (Map.Entry<K, V> me: map.entrySet()) { final K nm = me.getKey(); final V val = me.getValue(); if (((nm instanceof Serializable) || (nm instanceof Externalizable)) && (val == null || (val instanceof Serializable) || (val instanceof Externalizable))) { try { s.writeObject(nm); s.writeObject(val); } catch (java.io.NotSerializableException ex) { logio.error("Unable to serialize entry: "+nm+'='+val); throw ex; } } else if (nm != null && debug) { logio.debug("Skip not-serializable entry: "+nm+'='+val); } } } s.writeObject(null); //denote end-of-map } /** Reads serializable entries back (serialized by {@link #smartWrite(ObjectOutputStream,Map)}). * * @param map the map to hold the data being read. If null and any data * is read, a new map (HashMap) is created and returned. * @return the map being read */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> smartRead(ObjectInputStream s, Map<K, V> map) throws IOException, ClassNotFoundException { for (;;) { final Object nm = s.readObject(); if (nm == null) break; //no more if (map == null) map = new HashMap<K,V>(); map.put((K)nm, (V)s.readObject()); } return map; } /** Writes only serializable elements of the specified collection. */ public static <T> void smartWrite(ObjectOutputStream s, Collection<T> col) throws IOException { if (col != null) { final boolean debug = logio.isDebugEnabled(); for (T val: col) { if ((val instanceof Serializable) || (val instanceof Externalizable)) { try { s.writeObject(val); } catch (java.io.NotSerializableException ex) { logio.error("Unable to serialize item: "+val); throw ex; } } else if (val != null && debug) { logio.debug("Skip not-serializable item: "+val); } } } s.writeObject(null); } /** Reads serializable elements back (serialized by {@link #smartWrite(ObjectOutputStream,Collection)}) * * @param col the collection to hold the data being read. If null and * and data is read, a new collection (LinkedList) is created and returned. * @return the collection being read */ @SuppressWarnings("unchecked") public static <T> Collection<T> smartRead(ObjectInputStream s, Collection<T> col) throws IOException, ClassNotFoundException { for (;;) { final Object val = s.readObject(); if (val == null) break; //no more if (col == null) col = new LinkedList<T>(); col.add((T)val); } return col; } /** Reads serializable elements back (serialized by {@link #smartWrite(ObjectOutputStream,Collection)}) * * @param col the collection to hold the data being read. If null and * and data is read, a new collection (LinkedList) is created and returned. * @return the collection being read * @since 6.0.0 */ @SuppressWarnings("unchecked") public static <T> List<T> smartRead(ObjectInputStream s, List<T> col) throws IOException, ClassNotFoundException { for (;;) { final Object val = s.readObject(); if (val == null) break; //no more if (col == null) col = new LinkedList<T>(); col.add((T)val); } return col; } /** Writes only serializable elements of the specified array. * <p>To read back, use {@link #smartRead(ObjectInputStream, Collection)}. * @since 3.0.0 */ public static <T> void smartWrite(ObjectOutputStream s, T[] ary) throws IOException { if (ary != null) { final boolean debug = logio.isDebugEnabled(); for (int j = 0; j < ary.length; ++j) { final T val = ary[j]; if ((val instanceof Serializable) || (val instanceof Externalizable)) { try { s.writeObject(val); } catch (java.io.NotSerializableException ex) { logio.error("Unable to serialize item: "+val); throw ex; } } else if (val != null && debug) { logio.debug("Skip not-serializable item: "+val); } } } s.writeObject(null); } /** Writes the given value only if it is serializable. * If not, null is written. * @since 5.0.7 */ public static void smartWrite(ObjectOutputStream s, Object val) throws IOException { final boolean bser = val instanceof java.io.Serializable || val instanceof java.io.Externalizable; s.writeObject(bser ? val: null); if (!bser && val != null && logio.isDebugEnabled()) logio.debug("Skip not-serializable object: "+val); } }