All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.io.SerializationUtils Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
/*
 * Copyright (c) CQSE GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.conqat.lib.commons.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.conqat.lib.commons.assertion.CCSMAssert;
import org.conqat.lib.commons.filesystem.FileSystemUtils;

/**
 * Utility methods for serialization.
 */
public class SerializationUtils {

	/** Serializes an object to byte array */
	public static byte[] serializeToByteArray(Serializable object) throws IOException {
		ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
		ObjectOutputStream out = FilteredObjectStreams.filteredOutputStream(outBuffer);
		try {
			out.writeObject(object);
		} catch (OutOfMemoryError e) {
			if (e.getMessage() != null && //
					(e.getMessage().matches("Required array length \\d+ \\+ \\d+ is too large")
							|| e.getMessage().equals("Requested array size exceeds VM limit"))) {
				OutOfMemoryError e1 = new OutOfMemoryError(String.format(
						"Cannot serialize instance of type %s as it is too large to fit into a single byte[].",
						object.getClass()));
				// Cannot construct OOM with a cause, so add it as suppressed at least.
				e1.addSuppressed(e);
				throw e1;
			}
			throw e;
		}
		// no need to put this in finally, as we do not block file handles.
		// Let the GC do the work
		out.close();
		return outBuffer.toByteArray();
	}

	/**
	 * Make use of StorageUtils#deserialize(byte[]) whenever possible. Only use this method as last
	 * resort. 
*
* Deserializes an object from byte array using a custom/given class loader. Important:The * caller has to ensure that the supplied class loader "knows" all classes to be deserialized. * Returns null if a null value is passed. * */ public static Serializable deserializeFromByteArray(byte[] bytes) throws IOException, ClassNotFoundException { if (bytes == null) { return null; } ObjectInputStream in = FilteredObjectStreams.filteredInputStream(new ByteArrayInputStream(bytes)); try { return (Serializable) in.readObject(); } finally { FileSystemUtils.close(in); } } /** * Returns a copy of the given object obtained by serialization and deserialization in memory. * */ @SuppressWarnings("unchecked") public static T cloneBySerialization(T t) { try { return (T) deserializeFromByteArray(serializeToByteArray(t)); } catch (IOException e) { CCSMAssert.fail("This should be impossible as we are working in memory!"); return null; } catch (ClassNotFoundException e) { CCSMAssert.fail("This should be impossible as we just had the object available!"); return null; } } /** * Inserts an int value to the given position in the byte array. The storage will require 4 bytes in * big endian byte order. */ public static void insertInt(int i, byte[] bytes, int position) { bytes[position++] = (byte) (i >> 24 & 0xff); bytes[position++] = (byte) (i >> 16 & 0xff); bytes[position++] = (byte) (i >> 8 & 0xff); bytes[position] = (byte) (i & 0xff); } /** * Extracts an int value from the given array position (4 bytes in big endian). This is the counter * part to {@link #insertInt(int, byte[], int)} . */ public static int extractInt(byte[] bytes, int position) { int result = bytes[position++] & 0xff; result <<= 8; result |= bytes[position++] & 0xff; result <<= 8; result |= bytes[position++] & 0xff; result <<= 8; result |= bytes[position++] & 0xff; return result; } /** * Can be used in a {@code private void writeObject(ObjectOutputStream stream) throws IOException} * implementation, to indicate that while the class implements {@link Serializable} it actually does * not support serialization. * * @param ignoredStream * Ignored input value. Can be provided to avoid unused parameter findings on their * {@code ObjectOutputStream} until TS-38759 is resolved. */ public static void unsupportedWriteObject(@Nullable ObjectOutputStream ignoredStream) { CCSMAssert.fail("Attempt to serialize an object, which should never be serialized"); } /** * Can be used in a * {@code private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException} * implementation, to indicate that while the class implements {@link Serializable} it actually does * not support deserialization. * * @param ignoredStream * Ignored input value. Can be provided to avoid unused parameter findings on their * {@code ObjectInputStream} until TS-38759 is resolved. */ public static void unsupportedReadObject(@Nullable ObjectInputStream ignoredStream) { CCSMAssert.fail("Attempt to deserialize an object, which should never be deserialized"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy