package at.gv.egiz.eaaf.core.impl.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Set; import org.springframework.lang.Nullable; import at.gv.egiz.eaaf.core.impl.utils.EaafObjectInputStream.Mode; public class EaafSerializationUtils { private EaafSerializationUtils() { } /** * Serialize a given Java object into a byte array. * * @param object Java object to serialize. * @return Serialized Java object */ @Nullable public static byte[] serialize(@Nullable Object object) { if (object == null) { return null; } final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(object); oos.flush(); } catch (final IOException ex) { throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex); } return baos.toByteArray(); } /** * Deserialize the byte array into an object with strict allow-list of classes. * *

* Allow all classes that exact match to elements in allow-list. *

* * @param bytes a serialized object * @param allowedClassName List of classnames that are explicit allowed for * deserialization * @return the result of deserializing the bytes */ @Nullable public static Object strictDeserialize(@Nullable byte[] bytes, Set> allowedClassName) { if (bytes == null) { return null; } try (ObjectInputStream ois = new EaafObjectInputStream(new ByteArrayInputStream(bytes), allowedClassName, null, Mode.STRICT)) { return ois.readObject(); } catch (final IOException ex) { throw new IllegalArgumentException("Failed to deserialize object", ex); } catch (final ClassNotFoundException ex) { throw new IllegalStateException("Failed to deserialize object type", ex); } } /** * Deserialize the byte array into an object with type-specific allow-list of * classes. * *

* Allow all classes that the same or a super-type of elements in * allow-list.
* Hint: Do NOT set {@link Object} as allowed class, because any class is * an super-type of {@link Object}. This method implementation allows * {@link Object} as explicit type with strict check-mode. *

* * @param bytes a serialized object * @param allowedClassName List of classes that are explicit allowed for * deserialization * @param initalClassType First / Initial class type that are required * @return the result of deserializing the bytes */ @Nullable public static Object typeSpecificDeserialize(@Nullable byte[] bytes, Set> allowedClassName, Class initalClassType) { if (bytes == null) { return null; } try (ObjectInputStream ois = new EaafObjectInputStream(new ByteArrayInputStream(bytes), allowedClassName, initalClassType, Mode.TYPE_SPECIFIC)) { return ois.readObject(); } catch (final IOException ex) { throw new IllegalArgumentException("Failed to deserialize object", ex); } catch (final ClassNotFoundException ex) { throw new IllegalStateException("Failed to deserialize object type", ex); } } }