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

org.gridkit.coherence.utils.pof.AutoPofSerializer Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2011-2013 Alexey Ragozin
 *
 * 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.gridkit.coherence.utils.pof;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

import com.tangosol.io.ReadBuffer.BufferInput;
import com.tangosol.io.Serializer;
import com.tangosol.io.WriteBuffer.BufferOutput;
import com.tangosol.io.pof.ConfigurablePofContext;
import com.tangosol.io.pof.PofBufferReader;
import com.tangosol.io.pof.PofBufferWriter;
import com.tangosol.io.pof.PofContext;
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofSerializer;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;
import com.tangosol.io.pof.PortableObjectSerializer;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.CacheService;
import com.tangosol.net.Cluster;
import com.tangosol.net.DefaultConfigurableCacheFactory;
import com.tangosol.net.NamedCache;
import com.tangosol.run.xml.XmlElement;
import com.tangosol.run.xml.XmlHelper;
import com.tangosol.util.Base;
import com.tangosol.util.UUID;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.EqualsFilter;
import com.tangosol.util.filter.NotFilter;
import com.tangosol.util.filter.PresentFilter;
import com.tangosol.util.processor.ConditionalPut;

/**
 * Automatic serializer utilising POF without using static configuration xml.
 * 
 * @author Alexey Ragozin ([email protected])
 */
public class AutoPofSerializer implements Serializer, PofContext {

	static boolean TRACE = false;
	
	private static final String AUTO_POF_SERVICE = "AUTO-POF-SERVICE";
	private static final String AUTO_POF_MAPPING = "AUTO_POF_MAPPING";

	private static final long TYPE_MAP_CONNECT_TIMEOUT = Long.getLong("gridkit.auto-pof.type-map-timeout", 10000);
	
	private static final int MAX_CONFIG_ID = Integer.getInteger("gridkit.auto-pof.max-config-id", 1000);
	private static final int MIN_AUTO_ID = Integer.getInteger("gridkit.auto-pof.min-auto-id", 10000);
	private static final boolean USE_PUBLIC_CACHE_CONFIG = Boolean.getBoolean("gridkit.auto-pof.use-public-cache-config");
	
	private static final String XML_FRAGMENT =
	""
+ 		""
+			"AUTO_POF_MAPPINGAUTO_POF_SCHEME"
+		""
+ 		""
+			""
+				"AUTO_POF_SCHEME"
+				"AUTO_POF_SERVICE"
+               ""
+			""
+		""
+	"";
	
	// base context to delegate system class serialization
	private ConfigurablePofContext context;
	private NamedCache typeMap;
	private SynchronousQueue typeMapGetter = new SynchronousQueue();
	
	private volatile Map, SerializationContext> classMap;  
	private volatile SerializationContext[] lowTypeIdMap = new SerializationContext[1024];
	private volatile SerializationContext[] highTypeIdMap = new SerializationContext[256];
	
	private ReflectionPofSerializer autoSerializer = new ReflectionPofSerializer();
	private int minAutoId = MIN_AUTO_ID;
	
	public AutoPofSerializer() {
		this(new ConfigurablePofContext(), null);
	}
	
	public AutoPofSerializer(String pofConfig) {
		this(new ConfigurablePofContext(pofConfig), null);
	}

	public AutoPofSerializer(String pofConfig, NamedCache typeMap) {
		this(new ConfigurablePofContext(pofConfig), typeMap);
	}

	public AutoPofSerializer(ConfigurablePofContext serializer, NamedCache typeMap) {
		this.context = serializer;
		this.typeMap = typeMap;
		initContextMap();
		initCustomPredefines();
		if (typeMap == null) {
			scheduleTypeMapConnection();
		}
	}
	
		
	private void initTypeMap() {
		if (typeMap == null) {
			try {
				typeMap = typeMapGetter.poll(TYPE_MAP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);
			} catch (InterruptedException e) {
				// do nothing
			}
			if (typeMap == null) {
				Base.err("AutoPofSerailizer cannot get type map cache, wait time exceeded");
				throw new IllegalStateException("Type map cache is not available");
			}			
			else {
				typeMapGetter = null;
			}
		}
	}

	private NamedCache getTypeMap() {
		if (USE_PUBLIC_CACHE_CONFIG) {
			return CacheFactory.getCache(AUTO_POF_MAPPING);
		}
		else {
			Cluster cluster = CacheFactory.getCluster();
			if (cluster.getServiceInfo(AUTO_POF_SERVICE) != null) {
				CacheService service = (CacheService) cluster.getService(AUTO_POF_SERVICE);
				return service.ensureCache(AUTO_POF_MAPPING, null);
			}
			else {
				XmlElement xml = XmlHelper.loadXml(XML_FRAGMENT);
				return new DefaultConfigurableCacheFactory(xml).ensureCache(AUTO_POF_MAPPING, null);
			}
		}
	}

	private synchronized void initContextMap() {
 		Map, SerializationContext> map = new HashMap, SerializationContext>();
 		for(int i = 0; i != MAX_CONFIG_ID; ++i) {
 			try {
 				PofSerializer serializer = context.getPofSerializer(i);
 				Class cls = context.getClass(i);
 				SerializationContext ctx = new SerializationContext();
 				ctx.pofId = i;
 				ctx.type = cls;
 				ctx.serializer = serializer;
 				map.put(cls, ctx);
 				putContext(ctx.pofId, ctx);
 			}
 			catch(IllegalArgumentException e) {
 				continue;
 			}
 		}
 		classMap = map; 		
	}
	
	private synchronized void initCustomPredefines() {
//		registerArraySerializer(minAutoId++ , Object[].class);
//		registerArraySerializer(minAutoId++ , UUID[].class);
		registerSerializationContext(minAutoId++, Collections.singleton(null).getClass(), new SingletonSetSerializer());
		registerSerializationContext(minAutoId++, Collections.singletonList(null).getClass(), new SingletonListSerializer());
		registerSerializationContext(minAutoId++, Collections.singletonMap(null, null).getClass(), new SingletonMapSerializer());
	}

	private void scheduleTypeMapConnection() {
		Runnable getter = new Runnable() {
			@Override
			public void run() {
				try {
					NamedCache typeMap = getTypeMap();
					typeMapGetter.put(typeMap);
				} catch (Exception e) {
					Base.err("Failed to connect to AutoPofSerializer type map cache. " + e.toString());
				}
			}
		};
		Thread thread = new Thread(getter);
		thread.setDaemon(true);
		thread.setName("AutoPofSerializer async cache connection");
		thread.start();
	}

	@Override
	public PofSerializer getPofSerializer(int userType) {
		SerializationContext ctx = contextById(userType);
		return ctx.serializer;
	}

	@Override
	public int getUserTypeIdentifier(Object obj) {
		SerializationContext ctx = contextByClass(obj.getClass());
		return ctx.pofId;
	}

	@Override
	@SuppressWarnings("rawtypes")
	public int getUserTypeIdentifier(Class cls) {
		SerializationContext ctx = contextByClass(cls);
		return ctx.pofId;
	}

	@Override
	public int getUserTypeIdentifier(String name) {
		throw new UnsupportedOperationException();
	}

	@Override
	public String getClassName(int userType) {
		SerializationContext ctx = contextById(userType);
		return ctx.type.getName();
	}

	@Override
	@SuppressWarnings("rawtypes")
	public Class getClass(int userType) {
		SerializationContext ctx = contextById(userType);
		return ctx.type;
	}

	@Override
	public boolean isUserType(Object obj) {
	    if (obj == null) {
	    	throw new IllegalArgumentException("Object cannot be null");
	    }
	    return isUserType(obj.getClass());
	}

	@Override
	@SuppressWarnings("rawtypes")
	public boolean isUserType(Class cls) {
		if (cls == Object[].class || cls == UUID[].class) {
			return false;
		}
		else if (cls.getName().startsWith("com.tangosol.util.ConverterCollections")) {
			return false;
		}

		return contextByClass(cls) != null;
	}

	@Override
	public boolean isUserType(String name) {
		throw new UnsupportedOperationException();
	}

	private SerializationContext contextByClass(Class cls) {
		SerializationContext ctx = classMap.get(cls);
		if (ctx == null) {
			return ensureContextByClass(cls);
		}
		return ctx;
	}
	
	private SerializationContext contextById(int id) {
		SerializationContext context = typeIdMap(id);
		if (context == null) {
			return ensureContextById(id);
		}
		else {
			return context;
		}
	}
	
	private SerializationContext typeIdMap(int id) {
		if (id < MIN_AUTO_ID) {
			return id >= lowTypeIdMap.length ? null : lowTypeIdMap[id];
		}
		else {
			int iid = id - MIN_AUTO_ID;
			return iid >= highTypeIdMap.length ? null : highTypeIdMap[iid];
		}		
	}
	
	private synchronized void putContext(int id, SerializationContext ctx) {
		if (id < MIN_AUTO_ID) {
			if (id >= lowTypeIdMap.length) {
				int newSize = (id + 1023) & (~1023);
				SerializationContext[] lowArray = new SerializationContext[newSize];
				System.arraycopy(lowTypeIdMap, 0, lowArray, 0, lowTypeIdMap.length);
				lowTypeIdMap = lowArray;
			}
			lowTypeIdMap[id] = ctx;
		}
		else {
			int iid = id - MIN_AUTO_ID;
			if (iid >= highTypeIdMap.length) {
				int newSize = (iid + 255) & (~255);
				SerializationContext[] highArray = new SerializationContext[newSize];
				System.arraycopy(highTypeIdMap, 0, highArray, 0, highTypeIdMap.length);
				highTypeIdMap = highArray;
			}
			highTypeIdMap[iid] = ctx;
		}
	}
	
	private synchronized SerializationContext ensureContextByClass(Class cls) {
		
		if (Throwable.class.isAssignableFrom(cls)) {
			SerializationContext ctx = classMap.get(Throwable.class);
			registerSerializationContext(ctx.pofId, cls, ctx.serializer);			
		}

		SerializationContext ctx = classMap.get(cls);
		if (ctx != null) {
			return ctx;
		}
		else {
			
			// try to import configure serializer on demand
			if (context.isUserType(cls)) {
				int id = context.getUserTypeIdentifier(cls);
				if (typeIdMap(id) != null && id < MIN_AUTO_ID) {
					ctx = importPofSerializer(id);
					if (classMap.get(cls) == ctx) {
						return ctx;
					}
				}
			}
			
			if (cls.isArray()) {
				registerArraySerializer(-1, cls);
			}
			else {
				registerTypeSerialser(-1, cls);
			}
			return classMap.get(cls);
		}
	}	

	private void registerArraySerializer(int userType, Class cls) {
		if (userType < 0) {
			userType = registerUserType(cls.getName());
		}
		
//		System.out.println("AUTOPOF: " + userType + "->" + cls.getName());
		
		PofSerializer serializer;
		Class base = cls.getComponentType();
		if (base.isPrimitive()) {
			if (base == boolean.class) {
				serializer = new BooleanArraySerializer();
			}
			else if (base == byte.class) {
				serializer = new ByteArraySerializer();
			}
			else if (base == char.class) {
				serializer = new CharArraySerializer();
			}
			else if (base == short.class) {
				serializer = new ShortArraySerializer();
			}
			else if (base == int.class) {
				serializer = new IntArraySerializer();
			}
			else if (base == long.class) {
				serializer = new LongArraySerializer();
			}
			else if (base == float.class) {
				serializer = new FloatArraySerializer();
			}
			else if (base == double.class) {
				serializer = new DoubleArraySerializer();
			}
			else {
				throw new IllegalArgumentException("Unknown primitive type - " + base.getName());
			}
		}
		else {
			Object[] proto = (Object[]) Array.newInstance(base, 0);
			serializer = new ObjectArraySerializer(proto);
		}		
		
		registerSerializationContext(userType, cls, serializer);
	}

	private void registerTypeSerialser(int userType, Class cls) {
		if (userType < 0) {
			userType = registerUserType(cls.getName());
		}

		PofSerializer serializer;
		if (isPofCompatible(cls)) {
			serializer = new PortableObjectSerializer(userType);
		}
		else {
			try {
				serializer = autoSerializer.getClassCodec(cls);
			} catch (IOException e) {
				throw new IllegalArgumentException(e.getMessage(), e.getCause());
			}
		}

		registerSerializationContext(userType, cls, serializer);
	}

	private boolean isPofCompatible(Class cls) {
		return PortableObject.class.isAssignableFrom(cls)
				&& hasDefaultConstructor(cls)
				&& hasSerializationCode(cls);		
	}

	private boolean hasDefaultConstructor(Class cls) {
		try {
			Constructor c = cls.getConstructor();
			return Modifier.isPublic(c.getModifiers());
		} catch (SecurityException e) {
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			return false;
		}
	}

	private boolean hasSerializationCode(Class cls) {
		if (hasReadExtrenal(cls) || hasWriteExtrenal(cls)) {
			return true;
		}
		else {
			return isPofCompatible(cls.getSuperclass()) && declaresNoFields(cls);
		}
	}
	
	private boolean declaresNoFields(Class cls) {
		for(Field f: cls.getDeclaredFields()) {
			if (!Modifier.isStatic(f.getModifiers())) {
				return false;
			}
		}
		return true;
	}

	private boolean hasReadExtrenal(Class cls) {
		try {
			cls.getDeclaredMethod("readExternal", PofReader.class);
			return true;
		} catch (SecurityException e) {
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			return false;
		}
	}

	private boolean hasWriteExtrenal(Class cls) {
		try {
			cls.getDeclaredMethod("writeExternal", PofWriter.class);
			return true;
		} catch (SecurityException e) {
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			return false;
		}
	}

	private void registerSerializationContext(int userType, Class cls, PofSerializer serializer) {
		SerializationContext ctx = new SerializationContext();
		ctx.pofId = userType;
		ctx.type = cls;
		ctx.serializer = serializer;
		
		Map, SerializationContext> cm = new HashMap, AutoPofSerializer.SerializationContext>(classMap);
		cm.put(cls, ctx);
		classMap = cm;
		
		putContext(userType, ctx);
	}
	
	private synchronized SerializationContext ensureContextById(int id) {
		SerializationContext ctx = typeIdMap(id);
		if (ctx != null) {
			return ctx;
		}
		else {
			if (id < MIN_AUTO_ID) {
				return importPofSerializer(id);
			}
			else {
				if (TRACE) {
					System.out.println("AUTO: requested " + id);
				}
				
				if (typeMap == null) {
					initTypeMap();
				}
				
				String cname = (String) typeMap.get(id); // new java.util.HashMap(typeMap)
				if (cname == null) {
					throw new IllegalArgumentException("Unknown POF user type " + id);
				}
				try {
					Class cls = Class.forName(cname, true, Thread.currentThread().getContextClassLoader());
					ensureContextByClass(cls);
					return typeIdMap(id);
				} catch (ClassNotFoundException e) {
					throw new IllegalArgumentException("Class is not found " + cname);
				}
			}
		}
	}

	private SerializationContext importPofSerializer(int id) {
		SerializationContext ctx;
		PofSerializer serializer = context.getPofSerializer(id);
		Class cls = context.getClass(id);
		ctx = new SerializationContext();
		ctx.pofId = id;
		ctx.type = cls;
		ctx.serializer = serializer;
		Map, SerializationContext> map = new HashMap, AutoPofSerializer.SerializationContext>(classMap);
		map.put(cls, ctx);
		classMap = map;
		putContext(ctx.pofId, ctx);
		
		return ctx;
	}

	private synchronized int registerUserType(String name) {
		if (typeMap == null) {
			initTypeMap();
		}
		while(true) {
			Integer id = (Integer) typeMap.get(name);
			if (id != null) {
				if (TRACE) {
					System.out.println("AUTOPOF: mapped " + name + " -> " + id);
				}
				return id;
			}
			Integer n = (Integer) typeMap.get("");
			int nn;
			if (n == null) {
				nn = minAutoId;
			}
			else {
				nn = n + 1;
			}
			Object x = typeMap.invoke("", new ConditionalPut(new EqualsFilter(IdentityExtractor.INSTANCE, n), nn, true));
			if (x != null) {
				continue;
			}
			// this may create fake id -> name mappings, but it is ok because they will never be used in POF stream
			typeMap.put(nn, name);
			typeMap.invoke(name, new ConditionalPut(new NotFilter(PresentFilter.INSTANCE), nn, true));
		}
	}
	
	public void serialize(BufferOutput out, Object o) throws IOException {
		PofBufferWriter writer = new PofBufferWriter(out, this);
		try {
			writer.writeObject(-1, o);
		} catch (RuntimeException e) {
			IOException ioex = new IOException(e.getMessage());

			ioex.initCause(e);
			throw ioex;
		}
	}

	public Object deserialize(BufferInput in) throws IOException {
		PofBufferReader reader = new PofBufferReader(in, this);
		try {
			return reader.readObject(-1);
		} catch (RuntimeException e) {
			IOException ioex = new IOException(e.getMessage());
			ioex.initCause(e);
			throw ioex;
		}
	}
	
	private static class SerializationContext {
		
		private Class type;
		private int pofId;
		private PofSerializer serializer;
		
	}
	
	private static class BooleanArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeBooleanArray(0, (boolean[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			boolean[] array = reader.readBooleanArray(0);
			reader.readRemainder();
			return array;
		}		
	}
	
	private static class ByteArraySerializer implements PofSerializer {

		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeByteArray(0, (byte[]) array);
			writer.writeRemainder(null);
		}

		@Override
		public Object deserialize(PofReader reader) throws IOException {
			byte[] array = reader.readByteArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class CharArraySerializer implements PofSerializer {

		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeCharArray(0, (char[]) array);
			writer.writeRemainder(null);
		}

		@Override
		public Object deserialize(PofReader reader) throws IOException {
			char[] array = reader.readCharArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class ShortArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeShortArray(0, (short[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			short[] array = reader.readShortArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class IntArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeIntArray(0, (int[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			int[] array = reader.readIntArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class LongArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeLongArray(0, (long[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			long[] array = reader.readLongArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class FloatArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeFloatArray(0, (float[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			float[] array = reader.readFloatArray(0);
			reader.readRemainder();
			return array;
		}		
	}

	private static class DoubleArraySerializer implements PofSerializer {
		
		@Override
		public void serialize(PofWriter writer, Object array) throws IOException {
			writer.writeDoubleArray(0, (double[]) array);
			writer.writeRemainder(null);
		}
		
		@Override
		public Object deserialize(PofReader reader) throws IOException {
			double[] array = reader.readDoubleArray(0);
			reader.readRemainder();
			return array;
		}		
	}
	
	private static class ObjectArraySerializer implements PofSerializer {
		
		private final Object[] prototype;
		
		public ObjectArraySerializer(Object[] prototype) {
			this.prototype = prototype;
		}

		@Override
		public void serialize(PofWriter writer, Object obj) throws IOException {
			Object[] array = (Object[]) obj;
			writer.writeObjectArray(0, array);
			writer.writeRemainder(null);
		}

		@Override
		public Object deserialize(PofReader reader) throws IOException {
			Object result = reader.readObjectArray(0, prototype);
			reader.readRemainder();
			if (((Object[])result).length == 0) {
				return prototype;
			}
			else {
				return result;
			}
		}		
	}
	
	private static class SingletonSetSerializer implements PofSerializer {

		@Override
		public Object deserialize(PofReader in) throws IOException {
			Object obj = in.readObject(1);
			in.readRemainder();
			return Collections.singleton(obj);
		}

		@Override
		@SuppressWarnings("rawtypes")
		public void serialize(PofWriter out, Object obj) throws IOException {
			Object[] el = ((Collection)obj).toArray();
			out.writeObject(1, el[0]);
			out.writeRemainder(null);
		}		
	}

	private static class SingletonListSerializer implements PofSerializer {
		
		@Override
		public Object deserialize(PofReader in) throws IOException {
			Object obj = in.readObject(1);
			in.readRemainder();
			return Collections.singletonList(obj);
		}
		
		@Override
		@SuppressWarnings("rawtypes")
		public void serialize(PofWriter out, Object obj) throws IOException {
			Object[] el = ((Collection)obj).toArray();
			out.writeObject(1, el[0]);
			out.writeRemainder(null);
		}		
	}

	private static class SingletonMapSerializer implements PofSerializer {
		
		@Override
		public Object deserialize(PofReader in) throws IOException {
			Object key = in.readObject(1);
			Object value = in.readObject(2);
			in.readRemainder();
			return Collections.singletonMap(key, value);
		}
		
		@Override
		@SuppressWarnings("rawtypes")
		public void serialize(PofWriter out, Object obj) throws IOException {
			Object[] key = ((Map)obj).keySet().toArray();
			out.writeObject(1, key[0]);
			out.writeObject(2, ((Map)obj).get(key[0]));
			out.writeRemainder(null);
		}		
	}

	public static class JavaSerializationSerializer implements Serializer, PofSerializer {

		public static Object fromBytes(byte[] buf) throws IOException {
			try {
				ByteArrayInputStream bis = new ByteArrayInputStream(buf);
				ObjectInputStream ois = new ObjectInputStream(bis);
				Object result = ois.readObject();
				return result;
			} catch (ClassNotFoundException e) {
				throw new IOException("Class not found '" + e.getMessage() + "'");
			}
		}

		public static byte[] toBytes(Object object) throws IOException {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(object);
			oos.close();
			byte[] byteArray = bos.toByteArray();
			return byteArray;
		}

		@Override
		public Object deserialize(BufferInput in) throws IOException {
			byte[] buf = new byte[in.available()];
			in.read(buf);
			return fromBytes(buf);
		}

		@Override
		public Object deserialize(PofReader in) throws IOException {
			byte[] data = in.readByteArray(0);
			in.readRemainder();
			return fromBytes(data);
		}
		
		@Override
		public void serialize(BufferOutput out, Object object) throws IOException {
			byte[] byteArray = toBytes(object);
			out.write(byteArray);
		}

		@Override
		public void serialize(PofWriter out, Object object)	throws IOException {
			byte[] data = toBytes(object);
			out.writeByteArray(0, data);
			out.writeRemainder(null);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy