org.jppf.serialization.Serializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jppf-common Show documentation
Show all versions of jppf-common Show documentation
JPPF, the open source grid computing solution
/*
* JPPF.
* Copyright (C) 2005-2015 JPPF Team.
* http://www.jppf.org
*
* 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.jppf.serialization;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
/**
* Instances of this class are intended to serialize object graphs to an underlying output stream.
* @author Laurent Cohen
* @exclude
*/
class Serializer {
/**
* The stream header ('JPPF' in ascii).
*/
static final byte[] HEADER = { 74, 80, 80, 70 };
/**
* Handle for null references.
*/
static final byte[] NULL_HANDLE = { 0, 0, 0, 0 };
/**
* Header written before a class descriptor.
*/
static final byte CLASS_HEADER = 1;
/**
* Header written before a serialized object.
*/
static final byte OBJECT_HEADER = 2;
/**
* Header written before a serialized object.
*/
static final byte NULL_OBJECT_HEADER = 3;
/**
* Special treatment when an object to serialize is a class.
*/
static final byte CLASS_OBJECT_HEADER = 4;
/**
* The stream serialized data is written to.
*/
ObjectOutputStream out;
/**
* Holds all class and object descriptors.
*/
SerializationCaches caches = new SerializationCaches();
/**
* Descriptor the class of the object currently being written.
*/
ClassDescriptor currentClassDescriptor;
/**
* The object currently being written.
*/
Object currentObject;
/**
* Temporary buffer used to write arrays of primitive values to the stream.
*/
private byte[] buf = new byte[4096];
/**
* Initialize this serializer with the specified output stream, and write the header.
* @param out the stream to which the serialized data is written.
* @throws IOException if an error occurs while writing the header.
*/
Serializer(final ObjectOutputStream out) throws IOException {
this.out = out;
out.write(HEADER);
}
/**
* Write the specified object to the output stream.
* @param obj the object to write.
* @throws Exception if any error occurs.
*/
void writeObject(final Object obj) throws Exception {
if (obj == null) out.writeByte(NULL_OBJECT_HEADER);
else if (obj instanceof Class) writeClassObject((Class) obj);
else {
Integer handle = caches.objectHandleMap.get(obj);
if (handle == null) {
handle = caches.newObjectHandle(obj);
writeObject(obj, handle);
} else {
out.writeByte(OBJECT_HEADER);
out.writeInt(handle);
}
}
}
/**
* Write the specified object to the output stream.
* @param obj the object to write.
* @param handle the object's handle
* @throws Exception if any error occurs.
*/
private void writeObject(final Object obj, final int handle) throws Exception {
Map, ClassDescriptor> map = new HashMap<>();
ClassDescriptor cd = caches.getClassDescriptor(obj.getClass(), map);
currentObject = obj;
currentClassDescriptor = cd;
writeClassDescriptors(map);
map = null;
out.writeByte(OBJECT_HEADER);
out.writeInt(handle);
out.writeInt(cd.handle);
//if (traceEnabled) try { log.trace("writing object " + obj + ", handle=" + handle + ", class=" + obj.getClass() + ", cd=" + cd); } catch(Exception e) {}
if (cd.array) writeArray(obj, cd);
else if (cd.enumType) {
String name = ((Enum) obj).name();
writeObject(name);
}
else writeFields(obj, cd);
}
/**
* Write the specified object to the output stream.
* @param obj the object to write.
* @throws Exception if any error occurs.
*/
private void writeClassObject(final Class obj) throws Exception {
Map, ClassDescriptor> map = new HashMap<>();
ClassDescriptor cd = caches.getClassDescriptor(obj, map);
currentObject = obj;
currentClassDescriptor = cd;
writeClassDescriptors(map);
out.writeByte(CLASS_OBJECT_HEADER);
out.writeInt(cd.handle);
}
/**
* Write the all fields, including those declared in the superclasses, for the specified object.
* @param obj the object whose fields are to be written.
* @param cd the object's class descriptor.
* @throws Exception if any error occurs.
*/
void writeFields(final Object obj, final ClassDescriptor cd) throws Exception {
ClassDescriptor tmpDesc = cd;
Deque stack = new LinkedBlockingDeque<>();
while (tmpDesc != null) {
stack.addFirst(tmpDesc);
tmpDesc = tmpDesc.superClass;
}
for (ClassDescriptor desc: stack) {
if (desc.hasWriteObject) {
Method m = SerializationReflectionHelper.getWriteObjectMethod(desc.clazz);
if (!m.isAccessible()) m.setAccessible(true);
//if (traceEnabled) try { log.trace("invoking writeObject() for class=" + desc + " on object " + obj.hashCode()); } catch(Exception e) { log.trace(e.getMessage(), e); }
try {
tmpDesc = currentClassDescriptor;
currentClassDescriptor = desc;
m.invoke(obj, out);
} finally {
currentClassDescriptor = tmpDesc;
}
}
else if (desc.externalizable) ((Externalizable) obj).writeExternal(out);
else writeDeclaredFields(obj, desc);
}
}
/**
* Write the fields for the specified object and class descriptor.
* @param obj the object whose fields are to be written.
* @param cd the object's class descriptor.
* @throws Exception if any error occurs.
*/
void writeDeclaredFields(final Object obj, final ClassDescriptor cd) throws Exception {
for (int i=0; i, ClassDescriptor> map) throws IOException {
if (map.isEmpty()) return;
out.writeByte(CLASS_HEADER);
out.writeInt(map.size());
for (Map.Entry, ClassDescriptor> entry: map.entrySet()) entry.getValue().write(out);
}
/**
* Write an array of booleans to the stream.
* @param array the array of boolean values to write.
* @throws Exception if any error occurs.
*/
private void writeBooleanArray(final boolean[] array) throws Exception {
for (int count=0; count < array.length;) {
int n = Math.min(buf.length, array.length - count);
for (int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy