blob: 224b97699c4247794211c548fc0421aab481e6c7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.pdx.internal;
import java.io.Externalizable;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Pattern;
import org.apache.logging.log4j.Logger;
import org.apache.geode.CancelException;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.RegionService;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.CopyOnWriteHashSet;
import org.apache.geode.internal.PdxSerializerObject;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.util.concurrent.CopyOnWriteWeakHashMap;
import org.apache.geode.pdx.FieldType;
import org.apache.geode.pdx.NonPortableClassException;
import org.apache.geode.pdx.PdxReader;
import org.apache.geode.pdx.PdxSerializationException;
import org.apache.geode.pdx.PdxWriter;
import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
import org.apache.geode.pdx.internal.unsafe.UnsafeWrapper;
/**
* The core of auto serialization which is used in both aspect and reflection-based
* auto-serialization. This simple manager class is a singleton which tracks the relevant fields for
* each class which is to be auto-serialized. This class used to be a singleton. But now every
* instance of ReflectionBasedAutoSerializer will have its own instance of this class. We allow
* instances of this class to be found so that tests can access internal apis that are not exposed
* on the public ReflectionBasedAutoSerializer.
*
* @since GemFire 6.6
*/
public class AutoSerializableManager {
private static final Logger logger = LogService.getLogger();
private static final String INIT_CLASSES_PARAM = "classes";
private static final String INIT_CHECK_PORTABILITY_PARAM = "check-portability";
private static final String OPT_IDENTITY = "identity";
private static final String OPT_EXCLUDE = "exclude";
/*
* Map of class and list of fields, we're interested in, for that class.
*/
private final Map<Class<?>, AutoClassInfo> classMap =
new CopyOnWriteWeakHashMap<Class<?>, AutoClassInfo>();
/*
* Mapping between class patterns and identity field patterns.
*/
private final List<String[]> identityPatterns = new CopyOnWriteArrayList<String[]>();
/*
* Mapping between class patterns and patterns of fields to exclude
*/
private final List<String[]> excludePatterns = new CopyOnWriteArrayList<String[]>();
/*
* This is an internal parameter which, when set either as a system property or via cache.xml will
* not evaluate any hardcoded excludes. This helps with testing as well as possibly debugging
* future customer issues.
*/
public static final String NO_HARDCODED_EXCLUDES_PARAM =
DistributionConfig.GEMFIRE_PREFIX + "auto.serialization.no.hardcoded.excludes";
private boolean noHardcodedExcludes = Boolean.getBoolean(NO_HARDCODED_EXCLUDES_PARAM);
/*
* Holds a set of regex patterns which match the list of classes we're interested in.
*/
private final Set<Pattern> classPatterns = new LinkedHashSet<Pattern>();
/*
* Hardcoded set of patterns which we always exclude.
*/
private Set<Pattern> hardcodedExclusions = new HashSet<Pattern>() {
{
add(Pattern.compile("org\\.apache\\.geode\\..*"));
add(Pattern.compile("com\\.gemstone\\..*"));
add(Pattern.compile("java\\..*"));
add(Pattern.compile("javax\\..*"));
}
};
/*
* Cache of class names which have been determined to be excluded from serialization. Built up
* within isRelevant().
*/
private final Set<String> cachedExcludedClasses = new CopyOnWriteHashSet<String>();
/*
* Cache of class names which have been determined to be included for serialization. Built up
* within isRelevant().
*/
private final Set<String> cachedIncludedClasses = new CopyOnWriteHashSet<String>();
/*
* Used to hold the class names which have triggered a warning because they have been determined
* that they should be auto serialized based on a pattern much but were not because that either do
* not have a public no-arg constructor or have explicit java serialization code.
*/
private final Set<String> loggedNoAutoSerializeMsg = new CopyOnWriteHashSet<String>();
private final ReflectionBasedAutoSerializer owner;
public ReflectionBasedAutoSerializer getOwner() {
return this.owner;
}
public static AutoSerializableManager create(ReflectionBasedAutoSerializer owner,
boolean checkPortability, String... patterns) {
AutoSerializableManager result = new AutoSerializableManager(owner);
result.reconfigure(checkPortability, patterns);
return result;
}
private AutoSerializableManager(ReflectionBasedAutoSerializer owner) {
this.owner = owner;
}
public Map<Class<?>, AutoClassInfo> getClassMap() {
return classMap;
}
private boolean checkPortability;
public void setCheckPortability(boolean b) {
this.checkPortability = b;
}
public boolean getCheckPortability() {
return this.checkPortability;
}
public void resetCachedTypes() {
classMap.clear();
}
public void resetCaches() {
identityPatterns.clear();
excludePatterns.clear();
resetCachedTypes();
}
public void resetAll() {
resetCaches();
this.checkPortability = false;
classPatterns.clear();
cachedIncludedClasses.clear();
cachedExcludedClasses.clear();
loggedNoAutoSerializeMsg.clear();
this.noHardcodedExcludes = Boolean.getBoolean(NO_HARDCODED_EXCLUDES_PARAM);
}
/*
* Helper method to determine whether the class of a given object is a class which we are
* interested in (de)serializing.
*
*
* @return true if the object should be considered for serialization or false otherwise
*/
private boolean isRelevant(Class<?> clazz) {
String className = clazz.getName();
// Do some short-circuiting if possible
if (cachedIncludedClasses.contains(className)) {
return true;
} else if (cachedExcludedClasses.contains(className)) {
return false;
}
boolean result = getOwner().isClassAutoSerialized(clazz);
if (result) {
cachedIncludedClasses.add(className);
} else {
cachedExcludedClasses.add(className);
}
return result;
}
/**
* Determines whether objects of the named class are excluded from auto-serialization. The classes
* that are excluded are Geode-internal classes and Java classes.
*
* @param className Class name including packages.
* @return <code>true</code> if the named class is excluded.
*/
public boolean isExcluded(String className) {
if (!noHardcodedExcludes) {
for (Pattern p : hardcodedExclusions) {
if (p.matcher(className).matches()) {
return true;
}
}
}
return false;
}
public boolean defaultIsClassAutoSerialized(Class<?> clazz) {
if (clazz.isEnum()) {
return false;
}
String className = clazz.getName();
if (isExcluded(className)) {
if (!PdxSerializerObject.class.isAssignableFrom(clazz)) {
return false;
}
}
for (Pattern p : classPatterns) {
if (p.matcher(className).matches()) {
if (hasValidConstructor(clazz, p) && !needsStandardSerialization(clazz, p)) {
return true;
} else {
return false;
}
}
}
return false;
}
/*
* Helper method to determine whether a class has a default constructor. That's needed so that it
* can be re-instantiated by PDX on de-serialization.
*
*/
private boolean hasValidConstructor(Class<?> clazz, Pattern matchedPattern) {
if (unsafe != null && !USE_CONSTRUCTOR) {
// unsafe allows us to create instances without a constructor
return true;
}
try {
clazz.getConstructor();
return true;
} catch (NoSuchMethodException nex) {
String className = clazz.getName();
if (!loggedNoAutoSerializeMsg.contains(className)) {
loggedNoAutoSerializeMsg.add(className);
logger.warn(
"Class {} matched with '{}' cannot be auto-serialized due to missing public no-arg constructor. Will attempt using Java serialization.",
className, matchedPattern.pattern());
}
return false;
}
}
private boolean needsStandardSerialization(Class<?> clazz, Pattern matchedPattern) {
if (Serializable.class.isAssignableFrom(clazz)) {
if (Externalizable.class.isAssignableFrom(clazz)) {
String className = clazz.getName();
if (!loggedNoAutoSerializeMsg.contains(className)) {
loggedNoAutoSerializeMsg.add(className);
logger.warn(
"Class {} matched with '{}' cannot be auto-serialized because it is Externalizable. Java serialization will be used instead of auto-serialization.",
className, matchedPattern.pattern());
}
return true;
} else {
if (getPrivateMethod(clazz, "writeObject", new Class[] {ObjectOutputStream.class},
Void.TYPE)) {
String className = clazz.getName();
if (!loggedNoAutoSerializeMsg.contains(className)) {
loggedNoAutoSerializeMsg.add(className);
logger.warn(
"Class {} matched with '{}' cannot be auto-serialized because it has a writeObject(ObjectOutputStream) method. Java serialization will be used instead of auto-serialization.",
className, matchedPattern.pattern());
}
return true;
} else if (getInheritableMethod(clazz, "writeReplace", null, Object.class)) {
String className = clazz.getName();
if (!loggedNoAutoSerializeMsg.contains(className)) {
loggedNoAutoSerializeMsg.add(className);
logger.warn(
"Class {} matched with '{}' cannot be auto-serialized because it has a writeReplace() method. Java serialization will be used instead of auto-serialization.",
className, matchedPattern.pattern());
}
return true;
}
}
}
return false;
}
/**
* Returns true if a non-private static method with given signature defined by given class, or
* false if none found.
*/
private static boolean getPrivateMethod(Class cl, String name, Class[] argTypes,
Class returnType) {
try {
Method meth = cl.getDeclaredMethod(name, argTypes);
int mods = meth.getModifiers();
return ((meth.getReturnType() == returnType) && ((mods & Modifier.STATIC) == 0)
&& ((mods & Modifier.PRIVATE) != 0));
} catch (NoSuchMethodException ex) {
return false;
}
}
/**
* Returns true if a non-static, non-abstract method with given signature provided it is defined
* by or accessible (via inheritance) by the given class, or false if no match found.
*/
private static boolean getInheritableMethod(Class cl, String name, Class[] argTypes,
Class returnType) {
Method meth = null;
Class defCl = cl;
while (defCl != null) {
try {
meth = defCl.getDeclaredMethod(name, argTypes);
break;
} catch (NoSuchMethodException ex) {
defCl = defCl.getSuperclass();
}
}
if ((meth == null) || (meth.getReturnType() != returnType)) {
return false;
}
int mods = meth.getModifiers();
if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
return false;
} else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
return true;
} else if ((mods & Modifier.PRIVATE) != 0) {
return (cl == defCl);
} else {
return packageEquals(cl, defCl);
}
}
/**
* Returns true if classes are defined in the same runtime package, false otherwise.
*/
private static boolean packageEquals(Class cl1, Class cl2) {
return (cl1.getClassLoader() == cl2.getClassLoader()
&& getPackageName(cl1).equals(getPackageName(cl2)));
}
/**
* Returns package name of given class.
*/
private static String getPackageName(Class cl) {
String s = cl.getName();
int i = s.lastIndexOf('[');
if (i >= 0) {
s = s.substring(i + 2);
}
i = s.lastIndexOf('.');
return (i >= 0) ? s.substring(0, i) : "";
}
/**
* Given a class, figure out which fields we're interested in serializing. The class' entire
* hierarchy will be traversed and used. Transients and statics will be ignored.
*
* @param clazz the <code>Class</code> we're interested in
* @return a list of fields to be used when this class is (de)serialized
*/
public List<PdxFieldWrapper> getFields(Class<?> clazz) {
return getClassInfo(clazz).getFields();
}
public AutoClassInfo getExistingClassInfo(Class<?> clazz) {
return classMap.get(clazz);
}
public AutoClassInfo getClassInfo(Class<?> clazz) {
Class<?> tmpClass = clazz;
AutoClassInfo classInfo = getExistingClassInfo(tmpClass);
if (classInfo == null) {
synchronized (classMap) {
classInfo = classMap.get(tmpClass);
if (classInfo != null)
return classInfo;
List<PdxFieldWrapper> fieldList = new ArrayList<PdxFieldWrapper>();
List<PdxFieldWrapper> variableLenFields = new ArrayList<PdxFieldWrapper>();
while (tmpClass != Object.class) {
Field[] fields = tmpClass.getDeclaredFields();
for (Field f : fields) {
if (getOwner().isFieldIncluded(f, clazz)) {
// Should this be reset at some point?
f.setAccessible(true);
FieldType ft = getOwner().getFieldType(f, clazz);
PdxFieldWrapper fw = PdxFieldWrapper.create(this, f, ft,
getOwner().getFieldName(f, clazz), getOwner().transformFieldValue(f, clazz),
getOwner().isIdentityField(f, clazz));
if (ft.isFixedWidth()) {
fieldList.add(fw);
} else {
variableLenFields.add(fw);
}
}
}
tmpClass = tmpClass.getSuperclass();
}
fieldList.addAll(variableLenFields);
classInfo = new AutoClassInfo(clazz, fieldList);
logger.info("Auto serializer generating type for {} for fields: {}", clazz,
classInfo.toFormattedString());
classMap.put(clazz, classInfo);
} // end sync
}
return classInfo;
}
public boolean defaultIsIdentityField(Field f, Class<?> clazz) {
return fieldMatches(f, clazz.getName(), identityPatterns);
}
public boolean defaultIsFieldIncluded(Field f, Class<?> clazz) {
return !Modifier.isTransient(f.getModifiers()) && !Modifier.isStatic(f.getModifiers())
&& !fieldMatches(f, clazz.getName(), excludePatterns);
}
public FieldType defaultGetFieldType(Field f, Class<?> clazz) {
return FieldType.get(f.getType());
}
private static class FieldWrapper {
private final Field field;
public FieldWrapper(Field f) {
this.field = f;
}
public Field getField() {
return this.field;
}
public int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getInt(o);
}
public void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
this.field.setInt(o, v);
}
public boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getBoolean(o);
}
public void setBoolean(Object o, boolean v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setBoolean(o, v);
}
public byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getByte(o);
}
public void setByte(Object o, byte v) throws IllegalArgumentException, IllegalAccessException {
this.field.setByte(o, v);
}
public short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getShort(o);
}
public void setShort(Object o, short v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setShort(o, v);
}
public char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getChar(o);
}
public void setChar(Object o, char v) throws IllegalArgumentException, IllegalAccessException {
this.field.setChar(o, v);
}
public long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getLong(o);
}
public void setLong(Object o, long v) throws IllegalArgumentException, IllegalAccessException {
this.field.setLong(o, v);
}
public float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getFloat(o);
}
public void setFloat(Object o, float v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setFloat(o, v);
}
public double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getDouble(o);
}
public void setDouble(Object o, double v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setDouble(o, v);
}
public Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.get(o);
}
public void setObject(Object o, Object v)
throws IllegalArgumentException, IllegalAccessException {
this.field.set(o, v);
}
@Override
public String toString() {
return field.toString();
}
}
private static class UnsafeFieldWrapper extends FieldWrapper {
private final long offset;
public UnsafeFieldWrapper(Field f) {
super(f);
this.offset = unsafe.objectFieldOffset(f);
}
@Override
public int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getInt(o, this.offset);
}
@Override
public void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
unsafe.putInt(o, this.offset, v);
}
@Override
public boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getBoolean(o, this.offset);
}
@Override
public void setBoolean(Object o, boolean v)
throws IllegalArgumentException, IllegalAccessException {
unsafe.putBoolean(o, this.offset, v);
}
@Override
public byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getByte(o, this.offset);
}
@Override
public void setByte(Object o, byte v) throws IllegalArgumentException, IllegalAccessException {
unsafe.putByte(o, this.offset, v);
}
@Override
public short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getShort(o, this.offset);
}
@Override
public void setShort(Object o, short v)
throws IllegalArgumentException, IllegalAccessException {
unsafe.putShort(o, this.offset, v);
}
@Override
public char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getChar(o, this.offset);
}
@Override
public void setChar(Object o, char v) throws IllegalArgumentException, IllegalAccessException {
unsafe.putChar(o, this.offset, v);
}
@Override
public long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getLong(o, this.offset);
}
@Override
public void setLong(Object o, long v) throws IllegalArgumentException, IllegalAccessException {
unsafe.putLong(o, this.offset, v);
}
@Override
public float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getFloat(o, this.offset);
}
@Override
public void setFloat(Object o, float v)
throws IllegalArgumentException, IllegalAccessException {
unsafe.putFloat(o, this.offset, v);
}
@Override
public double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getDouble(o, this.offset);
}
@Override
public void setDouble(Object o, double v)
throws IllegalArgumentException, IllegalAccessException {
unsafe.putDouble(o, this.offset, v);
}
@Override
public Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
return unsafe.getObject(o, this.offset);
}
@Override
public void setObject(Object o, Object v)
throws IllegalArgumentException, IllegalAccessException {
unsafe.putObject(o, this.offset, v);
}
}
// unsafe will be null if the Unsafe class is not available or SAFE was requested.
// We attempt to use Unsafe by default for best performance.
@Immutable
private static final UnsafeWrapper unsafe;
static {
UnsafeWrapper tmp = null;
// only use Unsafe if SAFE was not explicitly requested
if (!Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.SAFE")) {
try {
tmp = new UnsafeWrapper();
// only throw an exception if UNSAFE was explicitly requested
} catch (RuntimeException ex) {
if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.UNSAFE")) {
throw ex;
}
} catch (Error ex) {
if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.UNSAFE")) {
throw ex;
}
}
}
unsafe = tmp;
}
public abstract static class PdxFieldWrapper {
private final FieldWrapper field;
private final String fieldName;
private final boolean transformValue;
private final AutoSerializableManager owner;
private final boolean isIdentityField;
protected PdxFieldWrapper(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
FieldWrapper tmp;
if (unsafe != null) {
tmp = new UnsafeFieldWrapper(f);
} else {
tmp = new FieldWrapper(f);
}
this.field = tmp;
this.fieldName = name;
this.transformValue = transformValue;
this.owner = owner;
this.isIdentityField = isIdentityField;
}
public static PdxFieldWrapper create(AutoSerializableManager owner, Field f, FieldType ft,
String name, boolean transformValue, boolean isIdentityField) {
switch (ft) {
case INT:
return new IntField(owner, f, name, transformValue, isIdentityField);
case BYTE:
return new ByteField(owner, f, name, transformValue, isIdentityField);
case LONG:
return new LongField(owner, f, name, transformValue, isIdentityField);
case BOOLEAN:
return new BooleanField(owner, f, name, transformValue, isIdentityField);
case CHAR:
return new CharField(owner, f, name, transformValue, isIdentityField);
case SHORT:
return new ShortField(owner, f, name, transformValue, isIdentityField);
case DOUBLE:
return new DoubleField(owner, f, name, transformValue, isIdentityField);
case FLOAT:
return new FloatField(owner, f, name, transformValue, isIdentityField);
case STRING:
return new StringField(owner, f, name, transformValue, isIdentityField);
case DATE:
return new DateField(owner, f, name, transformValue, isIdentityField);
case BYTE_ARRAY:
return new ByteArrayField(owner, f, name, transformValue, isIdentityField);
case STRING_ARRAY:
return new StringArrayField(owner, f, name, transformValue, isIdentityField);
case ARRAY_OF_BYTE_ARRAYS:
return new ByteArrayArrayField(owner, f, name, transformValue, isIdentityField);
case BOOLEAN_ARRAY:
return new BooleanArrayField(owner, f, name, transformValue, isIdentityField);
case CHAR_ARRAY:
return new CharArrayField(owner, f, name, transformValue, isIdentityField);
case SHORT_ARRAY:
return new ShortArrayField(owner, f, name, transformValue, isIdentityField);
case INT_ARRAY:
return new IntArrayField(owner, f, name, transformValue, isIdentityField);
case LONG_ARRAY:
return new LongArrayField(owner, f, name, transformValue, isIdentityField);
case FLOAT_ARRAY:
return new FloatArrayField(owner, f, name, transformValue, isIdentityField);
case DOUBLE_ARRAY:
return new DoubleArrayField(owner, f, name, transformValue, isIdentityField);
case OBJECT_ARRAY:
return new ObjectArrayField(owner, f, name, transformValue, isIdentityField);
case OBJECT:
return new ObjectField(owner, f, name, transformValue, isIdentityField);
default:
throw new IllegalStateException("unhandled field type " + ft);
}
}
public boolean getCheckPortability() {
return this.owner.getCheckPortability();
}
public Field getField() {
return this.field.getField();
}
public String getName() {
return this.fieldName;
}
public boolean transform() {
return this.transformValue;
}
public abstract void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite);
public abstract void serializeValue(PdxWriterImpl writer, Object newValue,
boolean optimizeWrite);
public abstract void deserialize(InternalPdxReader reader, Object obj);
public abstract void orderedDeserialize(InternalPdxReader reader, Object obj);
protected Object readTransformIf(Object o, Object serializedValue)
throws IllegalArgumentException, IllegalAccessException {
if (!transform())
return serializedValue;
return readTransform(o, serializedValue);
}
protected Object readTransform(Object o, Object serializedValue)
throws IllegalArgumentException, IllegalAccessException {
return this.owner.getOwner().readTransform(getField(), o.getClass(), serializedValue);
}
protected void handleException(boolean serialization, Object obj, Exception ex) {
AutoSerializableManager.handleException(ex, serialization, getName(), obj);
}
protected int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getInt(o);
}
protected void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
this.field.setInt(o, v);
}
protected boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getBoolean(o);
}
protected void setBoolean(Object o, boolean v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setBoolean(o, v);
}
protected byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getByte(o);
}
protected void setByte(Object o, byte v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setByte(o, v);
}
protected short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getShort(o);
}
protected void setShort(Object o, short v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setShort(o, v);
}
protected char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getChar(o);
}
protected void setChar(Object o, char v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setChar(o, v);
}
protected long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getLong(o);
}
protected void setLong(Object o, long v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setLong(o, v);
}
protected float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getFloat(o);
}
protected void setFloat(Object o, float v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setFloat(o, v);
}
protected double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getDouble(o);
}
protected void setDouble(Object o, double v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setDouble(o, v);
}
protected Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
return this.field.getObject(o);
}
protected void setObject(Object o, Object v)
throws IllegalArgumentException, IllegalAccessException {
this.field.setObject(o, v);
}
public boolean isIdentityField() {
return this.isIdentityField;
}
@Override
public String toString() {
return this.fieldName + ": " + field.toString();
}
}
public static class IntField extends PdxFieldWrapper {
public IntField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeInt(getInt(obj));
} else {
writer.writeInt(getName(), getInt(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeInt((Integer) newValue);
} else {
writer.writeInt(getName(), (Integer) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readInt(pf)));
} else {
setInt(obj, reader.readInt(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readInt()));
} else {
setInt(obj, reader.readInt());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ByteField extends PdxFieldWrapper {
public ByteField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeByte(getByte(obj));
} else {
writer.writeByte(getName(), getByte(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeByte((Byte) newValue);
} else {
writer.writeByte(getName(), (Byte) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readByte(pf)));
} else {
setByte(obj, reader.readByte(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readByte()));
} else {
setByte(obj, reader.readByte());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class LongField extends PdxFieldWrapper {
public LongField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeLong(getLong(obj));
} else {
writer.writeLong(getName(), getLong(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeLong((Long) newValue);
} else {
writer.writeLong(getName(), (Long) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readLong(pf)));
} else {
setLong(obj, reader.readLong(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readLong()));
} else {
setLong(obj, reader.readLong());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class BooleanField extends PdxFieldWrapper {
public BooleanField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeBoolean(getBoolean(obj));
} else {
writer.writeBoolean(getName(), getBoolean(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeBoolean((Boolean) newValue);
} else {
writer.writeBoolean(getName(), (Boolean) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readBoolean(pf)));
} else {
setBoolean(obj, reader.readBoolean(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readBoolean()));
} else {
setBoolean(obj, reader.readBoolean());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class CharField extends PdxFieldWrapper {
public CharField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeChar(getChar(obj));
} else {
writer.writeChar(getName(), getChar(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeChar((Character) newValue);
} else {
writer.writeChar(getName(), (Character) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readChar(pf)));
} else {
setChar(obj, reader.readChar(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readChar()));
} else {
setChar(obj, reader.readChar());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ShortField extends PdxFieldWrapper {
public ShortField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeShort(getShort(obj));
} else {
writer.writeShort(getName(), getShort(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeShort((Short) newValue);
} else {
writer.writeShort(getName(), (Short) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readShort(pf)));
} else {
setShort(obj, reader.readShort(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readShort()));
} else {
setShort(obj, reader.readShort());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class FloatField extends PdxFieldWrapper {
public FloatField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeFloat(getFloat(obj));
} else {
writer.writeFloat(getName(), getFloat(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeFloat((Float) newValue);
} else {
writer.writeFloat(getName(), (Float) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readFloat(pf)));
} else {
setFloat(obj, reader.readFloat(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readFloat()));
} else {
setFloat(obj, reader.readFloat());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class DoubleField extends PdxFieldWrapper {
public DoubleField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
if (optimizeWrite) {
writer.writeDouble(getDouble(obj));
} else {
writer.writeDouble(getName(), getDouble(obj));
}
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeDouble((Double) newValue);
} else {
writer.writeDouble(getName(), (Double) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readDouble(pf)));
} else {
setDouble(obj, reader.readDouble(pf));
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
if (transform()) {
setObject(obj, readTransform(obj, reader.readDouble()));
} else {
setDouble(obj, reader.readDouble());
}
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ObjectField extends PdxFieldWrapper {
public ObjectField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeObject(newValue, getCheckPortability());
} else {
writer.writeObject(getName(), newValue, getCheckPortability());
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readObject(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readObject()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class StringField extends PdxFieldWrapper {
public StringField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeString((String) newValue);
} else {
writer.writeString(getName(), (String) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readString(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readString()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class DateField extends PdxFieldWrapper {
public DateField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeDate((Date) newValue);
} else {
writer.writeDate(getName(), (Date) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readDate(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readDate()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ByteArrayField extends PdxFieldWrapper {
public ByteArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeByteArray((byte[]) newValue);
} else {
writer.writeByteArray(getName(), (byte[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readByteArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readByteArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class BooleanArrayField extends PdxFieldWrapper {
public BooleanArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeBooleanArray((boolean[]) newValue);
} else {
writer.writeBooleanArray(getName(), (boolean[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readBooleanArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readBooleanArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ShortArrayField extends PdxFieldWrapper {
public ShortArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeShortArray((short[]) newValue);
} else {
writer.writeShortArray(getName(), (short[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readShortArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readShortArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class CharArrayField extends PdxFieldWrapper {
public CharArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeCharArray((char[]) newValue);
} else {
writer.writeCharArray(getName(), (char[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readCharArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readCharArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class IntArrayField extends PdxFieldWrapper {
public IntArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeIntArray((int[]) newValue);
} else {
writer.writeIntArray(getName(), (int[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readIntArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readIntArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class LongArrayField extends PdxFieldWrapper {
public LongArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeLongArray((long[]) newValue);
} else {
writer.writeLongArray(getName(), (long[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readLongArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readLongArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class FloatArrayField extends PdxFieldWrapper {
public FloatArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeFloatArray((float[]) newValue);
} else {
writer.writeFloatArray(getName(), (float[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readFloatArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readFloatArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class DoubleArrayField extends PdxFieldWrapper {
public DoubleArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeDoubleArray((double[]) newValue);
} else {
writer.writeDoubleArray(getName(), (double[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readDoubleArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readDoubleArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class StringArrayField extends PdxFieldWrapper {
public StringArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeStringArray((String[]) newValue);
} else {
writer.writeStringArray(getName(), (String[]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readStringArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readStringArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ByteArrayArrayField extends PdxFieldWrapper {
public ByteArrayArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeArrayOfByteArrays((byte[][]) newValue);
} else {
writer.writeArrayOfByteArrays(getName(), (byte[][]) newValue);
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readArrayOfByteArrays(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readArrayOfByteArrays()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
public static class ObjectArrayField extends PdxFieldWrapper {
public ObjectArrayField(AutoSerializableManager owner, Field f, String name,
boolean transformValue, boolean isIdentityField) {
super(owner, f, name, transformValue, isIdentityField);
}
@Override
public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
try {
serializeValue(writer, getObject(obj), optimizeWrite);
} catch (Exception ex) {
handleException(true, obj, ex);
}
}
@Override
public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
if (optimizeWrite) {
writer.writeObjectArray((Object[]) newValue, getCheckPortability());
} else {
writer.writeObjectArray(getName(), (Object[]) newValue, getCheckPortability());
}
}
@Override
public void deserialize(InternalPdxReader reader, Object obj) {
PdxField pf = reader.getPdxField(getName());
if (pf != null) {
try {
setObject(obj, readTransformIf(obj, reader.readObjectArray(pf)));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
@Override
public void orderedDeserialize(InternalPdxReader reader, Object obj) {
try {
setObject(obj, readTransformIf(obj, reader.readObjectArray()));
} catch (Exception ex) {
handleException(false, obj, ex);
}
}
}
/**
* Given an object, use its class to determine which fields are to be used when (de)serializing.
*
* @param obj the object whose class we're interested in
* @return a list of fields to be used when this object's class is (de)serialized
*/
public List<PdxFieldWrapper> getFields(Object obj) {
return getFields(obj.getClass());
}
/**
* Using the given PdxWriter, write out the relevant fields for the object instance passed in.
*
* @param writer the <code>PdxWriter</code> to use when writing the object
* @param obj the object to serialize
* @return <code>true</code> if the object was serialized, <code>false</code> otherwise
*/
public boolean writeData(PdxWriter writer, Object obj) {
if (isRelevant(obj.getClass())) {
writeData(writer, obj, getClassInfo(obj.getClass()));
return true;
}
return false;
}
private static void handleException(Exception ex, boolean serialization, String fieldName,
Object obj) {
if (ex instanceof CancelException) {
// fix for bug 43936
throw (CancelException) ex;
} else if (ex instanceof NonPortableClassException) {
throw (NonPortableClassException) ex;
} else {
throw new PdxSerializationException((serialization ? "Serialization" : "Deserialization")
+ " error on field " + fieldName + " for class " + obj.getClass().getName(), ex);
}
}
/**
* Using the given PdxWriter, write out the fields which have been passed in.
*
* @param writer the <code>PdxWriter</code> to use when writing the object
* @param obj the object to serialize
* @param autoClassInfo a <code>List</code> of <code>Field</code>s which are to be written out
*/
public void writeData(PdxWriter writer, Object obj, AutoClassInfo autoClassInfo) {
PdxWriterImpl w = (PdxWriterImpl) writer;
boolean optimizeFieldWrites = false;
if (autoClassInfo.getSerializedType() != null) {
// check to see if we have unread data for this instance
if (w.initUnreadData() == null) {
// we don't so we can optimize the field writes since
// we will write them in the correct order
optimizeFieldWrites = true;
}
}
for (PdxFieldWrapper f : autoClassInfo.getFields()) {
// System.out.println("DEBUG writing field=" + f.getField().getName() + " offset=" +
// ((PdxWriterImpl)writer).position());
if (f.transform()) {
try {
Object newValue =
getOwner().writeTransform(f.getField(), obj.getClass(), f.getObject(obj));
f.serializeValue(w, newValue, optimizeFieldWrites);
} catch (Exception ex) {
f.handleException(true, obj, ex);
}
} else {
f.serialize(w, obj, optimizeFieldWrites);
}
if (f.isIdentityField() && w.definingNewPdxType()) {
try {
w.markIdentityField(f.getName());
} catch (Exception ex) {
handleException(ex, true, f.getName(), obj);
}
}
}
if (autoClassInfo.getSerializedType() == null) {
autoClassInfo.setSerializedType(w.getAutoPdxType());
}
}
private static final boolean USE_CONSTRUCTOR =
!Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "autopdx.ignoreConstructor");
/**
* Using the given PdxReader, recreate the given object.
*
* @param reader the <code>PdxReader</code> to use when reading the object
* @param clazz the class of the object to re-create
*/
public Object readData(PdxReader reader, Class<?> clazz) {
Object result = null;
if (isRelevant(clazz)) {
AutoClassInfo ci = getClassInfo(clazz);
result = ci.newInstance(clazz);
InternalPdxReader ri = (InternalPdxReader) reader;
PdxType pt = ri.getPdxType();
if (ci.matchesPdxType(pt)) {
pt.setAutoInfo(ci);
ri.orderedDeserialize(result, ci);
} else {
for (PdxFieldWrapper f : ci.getFields()) {
f.deserialize(ri, result);
}
}
}
return result;
}
/**
* Add a new class pattern / identity-field pattern tuple
*
* @param classPattern the class pattern
* @param fieldPattern the pattern to identify a field as an identity field within the given class
* pattern
*/
public void addIdentityPattern(String classPattern, String fieldPattern) {
identityPatterns.add(new String[] {classPattern, fieldPattern});
}
/**
* Return the identity patterns. The patterns are returned as a <code>List</code> of
* <code>String</code> arrays of size 2 - essentially a tuple of the form
*
* <pre>
* (classPattern, identityPattern)
* </pre>
*
* @return the identity patterns
*/
public List<String[]> getIdentityPatterns() {
return identityPatterns;
}
/**
* Add a new class pattern / exclude-field pattern tuple
*
* @param classPattern the class pattern
* @param fieldPattern the pattern to exclude a field from serialization within the given class
* pattern
*/
public void addExcludePattern(String classPattern, String fieldPattern) {
excludePatterns.add(new String[] {classPattern, fieldPattern});
}
/**
* Return the exclude patterns. The patterns are returned as a <code>List</code> of
* <code>String</code> arrays of size 2 - essentially a tuple of the form
*
* <pre>
* (classPattern, excludePattern)
* </pre>
*
* @return the exclude patterns
*/
public List<String[]> getExcludePatterns() {
return excludePatterns;
}
/*
* Helper method which determines whether a given field matches a set of class/field patterns.
*
* @param field the <code>Field</code> to consider
*
* @param field the className which references this field
*
* @param matches a map containing the
*
*/
private boolean fieldMatches(Field field, String className, List<String[]> matches) {
String fieldName = field.getName();
for (String[] e : matches) {
if (className.matches(e[0]) && fieldName.matches(e[1])) {
return true;
}
}
return false;
}
/**
* Holds meta information about a class that we have auto serialized.
*
*/
public static class AutoClassInfo {
private final WeakReference<Class<?>> clazzRef;
/**
* The fields that describe the class
*/
private final List<PdxFieldWrapper> fields;
/**
* The pdxType ids that we are known to exactly match.
*/
private final Set<Integer> matchingPdxIds = new CopyOnWriteArraySet<Integer>();
/**
* The pdxType ids that do not exactly match our class. Either their field order differs it they
* have extra or missing fields.
*/
private final Set<Integer> mismatchingPdxIds = new CopyOnWriteArraySet<Integer>();
/**
* The PdxType created by the first serialization by the auto serializer.
*/
private PdxType serializedType = null;
public AutoClassInfo(Class<?> clazz, List<PdxFieldWrapper> fields) {
this.clazzRef = new WeakReference<Class<?>>(clazz);
this.fields = fields;
}
public String toFormattedString() {
StringBuffer sb = new StringBuffer();
boolean first = true;
for (Object o : this.fields) {
if (first) {
first = false;
sb.append('\n');
}
sb.append(" ").append(o).append('\n');
}
return sb.toString();
}
public Object newInstance(Class<?> clazz) {
Object result;
try {
if (unsafe != null && !USE_CONSTRUCTOR) {
result = unsafe.allocateInstance(clazz);
} else {
result = clazz.newInstance();
}
} catch (Exception ex) {
throw new PdxSerializationException(
String.format("Could not create an instance of a class %s",
clazz.getName()),
ex);
}
return result;
}
public void setSerializedType(PdxType v) {
this.serializedType = v;
}
public PdxType getSerializedType() {
return this.serializedType;
}
public Class<?> getInfoClass() {
return this.clazzRef.get();
}
public List<PdxFieldWrapper> getFields() {
return this.fields;
}
public boolean matchesPdxType(PdxType t) {
Integer pdxTypeId = Integer.valueOf(t.getTypeId());
if (this.matchingPdxIds.contains(pdxTypeId)) {
return true;
} else if (this.mismatchingPdxIds.contains(pdxTypeId)) {
return false;
} else if (checkForMatch(t)) {
this.matchingPdxIds.add(pdxTypeId);
return true;
} else {
this.mismatchingPdxIds.add(pdxTypeId);
return false;
}
}
private boolean checkForMatch(PdxType t) {
if (this.fields.size() != t.getUndeletedFieldCount()) {
return false;
}
Iterator<PdxField> pdxIt = t.getFields().iterator();
for (PdxFieldWrapper f : this.fields) {
PdxField pdxF = pdxIt.next();
if (pdxF.isDeleted()) {
return false; // If the type has a deleted field then we can't do ordered deserialization
// because we need to skip over the deleted field's bytes.
}
if (!f.getName().equals(pdxF.getFieldName())) {
return false;
}
if (!FieldType.get(f.getField().getType()).equals(pdxF.getFieldType())) {
return false;
}
}
return true;
}
@Override
public String toString() {
return "AutoClassInfo [fields=" + fields + "]";
}
}
public void init(Properties props) {
resetAll();
if (props != null) {
Enumeration<?> it = props.propertyNames();
while (it.hasMoreElements()) {
Object o = it.nextElement();
if (o instanceof String) {
String key = (String) o;
if (INIT_CLASSES_PARAM.equals(key)) {
String propValue = props.getProperty(INIT_CLASSES_PARAM);
if (propValue != null) {
processInitParams(propValue);
}
} else if (INIT_CHECK_PORTABILITY_PARAM.equals(key)) {
String propValue = props.getProperty(INIT_CHECK_PORTABILITY_PARAM);
if (propValue != null) {
setCheckPortability(Boolean.parseBoolean(propValue));
}
} else if (NO_HARDCODED_EXCLUDES_PARAM.equals(key)) {
if (props.getProperty(NO_HARDCODED_EXCLUDES_PARAM) != null) {
noHardcodedExcludes = true;
}
} else {
throw new IllegalArgumentException(
"ReflectionBasedAutoSerializer: unknown init property \"" + key + "\"");
}
} else {
throw new IllegalArgumentException(
"ReflectionBasedAutoSerializer: unknown non-String init property \"" + o + "\"");
}
}
}
}
public Properties getConfig() {
Properties props = new Properties();
if (classPatterns.isEmpty()) {
return props;
}
StringBuilder sb = new StringBuilder();
// This is so that we can exclude duplicates
// LinkedHashSet is used to preserve the order of classPatterns. See bug 52286.
Set<String> tmp = new LinkedHashSet<String>();
for (Pattern p : classPatterns) {
tmp.add(p.pattern());
}
for (Iterator<String> i = tmp.iterator(); i.hasNext();) {
String s = i.next();
sb.append(s);
if (i.hasNext()) {
sb.append(", ");
}
}
if (getIdentityPatterns().size() > 0) {
sb.append(", ");
for (Iterator<String[]> i = getIdentityPatterns().iterator(); i.hasNext();) {
String[] s = i.next();
sb.append(s[0]).append("#" + OPT_IDENTITY + "=").append(s[1]);
if (i.hasNext()) {
sb.append(", ");
}
}
}
if (getExcludePatterns().size() > 0) {
sb.append(", ");
for (Iterator<String[]> i = getExcludePatterns().iterator(); i.hasNext();) {
String[] s = i.next();
sb.append(s[0]).append("#" + OPT_EXCLUDE + "=").append(s[1]);
if (i.hasNext()) {
sb.append(", ");
}
}
}
props.put(INIT_CLASSES_PARAM, sb.toString());
if (getCheckPortability()) {
props.put(INIT_CHECK_PORTABILITY_PARAM, "true");
}
return props;
}
public void reconfigure(boolean b, String... patterns) {
resetAll();
setCheckPortability(b);
for (String c : patterns) {
processInitParams(c);
}
}
private void processInitParams(String value) {
String identityPattern;
String excludePattern;
for (String s : value.split("[, ]+")) {
if (s.length() > 0) {
// Let's check for any additional embedded params...
String[] split = s.split("#");
for (int i = 1; i < split.length; i++) {
identityPattern = null;
excludePattern = null;
String[] paramVals = split[i].split("=");
if (paramVals.length != 2) {
throw new IllegalArgumentException(
"Unable to correctly process auto serialization init value: " + value);
}
if (OPT_IDENTITY.equalsIgnoreCase(paramVals[0])) {
identityPattern = paramVals[1];
} else if (OPT_EXCLUDE.equalsIgnoreCase(paramVals[0])) {
excludePattern = paramVals[1];
} else {
throw new IllegalArgumentException(
"Unable to correctly process auto serialization init value: " + value);
}
if (identityPattern != null) {
addIdentityPattern(split[0], identityPattern);
}
if (excludePattern != null) {
addExcludePattern(split[0], excludePattern);
}
}
classPatterns.add(Pattern.compile(split[0]));
}
}
}
private RegionService cache;
public RegionService getRegionService() {
return this.cache;
}
public void setRegionService(RegionService rs) {
this.cache = rs;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (checkPortability ? 1231 : 1237);
result = prime * result + ((classPatterns == null) ? 0 : classPatterns.hashCode());
result = prime * result + ((excludePatterns == null) ? 0 : excludePatterns.hashCode());
result = prime * result + ((identityPatterns == null) ? 0 : identityPatterns.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AutoSerializableManager other = (AutoSerializableManager) obj;
if (checkPortability != other.checkPortability)
return false;
if (classPatterns == null) {
if (other.classPatterns != null)
return false;
} else if (!classPatterns.equals(other.classPatterns))
return false;
if (excludePatterns == null) {
if (other.excludePatterns != null)
return false;
} else if (!excludePatterns.equals(other.excludePatterns))
return false;
if (identityPatterns == null) {
if (other.identityPatterns != null)
return false;
} else if (!identityPatterns.equals(other.identityPatterns))
return false;
return true;
}
}