IGNITE-4538: Improved messages for BinaryMarshaller field read errors. This closes #1470.
(cherry picked from commit f52ba0f) Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1118c728 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1118c728 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1118c728 Branch: refs/heads/ignite-gg-8.0.3.ea6-clients-test Commit: 1118c72837096f29ff58065137f82763831c2c85 Parents: 5424b70 Author: Alexandr Kuramshin <[email protected]> Authored: Thu Feb 16 16:09:22 2017 +0700 Committer: Alexandr Kuramshin <[email protected]> Committed: Wed Mar 1 17:58:25 2017 +0700 ---------------------------------------------------------------------- .../internal/binary/BinaryClassDescriptor.java | 81 +++--- .../internal/binary/BinaryFieldAccessor.java | 56 ++-- .../internal/binary/BinaryReaderExImpl.java | 284 ++++++++++++++++--- .../ignite/internal/binary/BinaryUtils.java | 11 +- .../binary/BinaryObjectExceptionSelfTest.java | 209 ++++++++++++++ 5 files changed, 542 insertions(+), 99 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/1118c728/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java index 3a72a31..5616c69 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java @@ -44,6 +44,7 @@ import org.apache.ignite.internal.processors.query.GridQueryProcessor; import org.apache.ignite.internal.util.GridUnsafe; import org.apache.ignite.internal.util.IgniteUtils; import org.apache.ignite.internal.util.tostring.GridToStringExclude; +import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.MarshallerExclusions; @@ -806,58 +807,66 @@ public class BinaryClassDescriptor { * @throws BinaryObjectException If failed. */ Object read(BinaryReaderExImpl reader) throws BinaryObjectException { - assert reader != null; - assert mode != BinaryWriteMode.OPTIMIZED : "OptimizedMarshaller should not be used here: " + cls.getName(); + try { + assert reader != null; + assert mode != BinaryWriteMode.OPTIMIZED : "OptimizedMarshaller should not be used here: " + cls.getName(); - Object res; + Object res; - switch (mode) { - case BINARY: - res = newInstance(); + switch (mode) { + case BINARY: + res = newInstance(); - reader.setHandle(res); + reader.setHandle(res); - if (serializer != null) - serializer.readBinary(res, reader); - else - ((Binarylizable)res).readBinary(reader); + if (serializer != null) + serializer.readBinary(res, reader); + else + ((Binarylizable)res).readBinary(reader); - break; + break; - case OBJECT: - res = newInstance(); + case OBJECT: + res = newInstance(); - reader.setHandle(res); + reader.setHandle(res); - for (BinaryFieldAccessor info : fields) - info.read(res, reader); + for (BinaryFieldAccessor info : fields) + info.read(res, reader); - break; + break; - default: - assert false : "Invalid mode: " + mode; + default: + assert false : "Invalid mode: " + mode; - return null; - } + return null; + } - if (readResolveMtd != null) { - try { - res = readResolveMtd.invoke(res); + if (readResolveMtd != null) { + try { + res = readResolveMtd.invoke(res); - reader.setHandle(res); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - if (e.getTargetException() instanceof BinaryObjectException) - throw (BinaryObjectException)e.getTargetException(); + reader.setHandle(res); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + catch (InvocationTargetException e) { + if (e.getTargetException() instanceof BinaryObjectException) + throw (BinaryObjectException)e.getTargetException(); - throw new BinaryObjectException("Failed to execute readResolve() method on " + res, e); + throw new BinaryObjectException("Failed to execute readResolve() method on " + res, e); + } } - } - return res; + return res; + } + catch (Exception e) { + if (S.INCLUDE_SENSITIVE && !F.isEmpty(typeName)) + throw new BinaryObjectException("Failed to deserialize object [typeName=" + typeName + ']', e); + else + throw new BinaryObjectException("Failed to deserialize object [typeId=" + typeId + ']', e); + } } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/1118c728/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java index af33b63..db683db 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryFieldAccessor.java @@ -26,6 +26,8 @@ import java.util.Map; import java.util.UUID; import org.apache.ignite.binary.BinaryObjectException; import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.U; /** @@ -35,6 +37,9 @@ public abstract class BinaryFieldAccessor { /** Field ID. */ protected final int id; + /** Field name */ + protected final String name; + /** Mode. */ protected final BinaryWriteMode mode; @@ -116,10 +121,12 @@ public abstract class BinaryFieldAccessor { * @param id Field ID. * @param mode Mode; */ - protected BinaryFieldAccessor(int id, BinaryWriteMode mode) { + protected BinaryFieldAccessor(Field field, int id, BinaryWriteMode mode) { + assert field != null; assert id != 0; assert mode != null; + this.name = field.getName(); this.id = id; this.mode = mode; } @@ -149,7 +156,26 @@ public abstract class BinaryFieldAccessor { * @param reader Reader. * @throws BinaryObjectException If failed. */ - public abstract void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException; + public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + try { + read0(obj, reader); + } + catch (Exception ex) { + if (S.INCLUDE_SENSITIVE && !F.isEmpty(name)) + throw new BinaryObjectException("Failed to read field [name=" + name + ']', ex); + else + throw new BinaryObjectException("Failed to read field [id=" + id + ']', ex); + } + } + + /** + * Read field. + * + * @param obj Object. + * @param reader Reader. + * @throws BinaryObjectException If failed. + */ + protected abstract void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException; /** * Base primitive field accessor. @@ -166,9 +192,7 @@ public abstract class BinaryFieldAccessor { * @param mode Mode. */ protected AbstractPrimitiveAccessor(Field field, int id, BinaryWriteMode mode) { - super(id, mode); - - assert field != null; + super(field, id, mode); offset = GridUnsafe.objectFieldOffset(field); } @@ -197,7 +221,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { byte val = reader.readByte(id); GridUnsafe.putByteField(obj, offset, val); @@ -227,7 +251,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { boolean val = reader.readBoolean(id); GridUnsafe.putBooleanField(obj, offset, val); @@ -257,7 +281,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { short val = reader.readShort(id); GridUnsafe.putShortField(obj, offset, val); @@ -287,7 +311,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { char val = reader.readChar(id); GridUnsafe.putCharField(obj, offset, val); @@ -317,7 +341,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { int val = reader.readInt(id); GridUnsafe.putIntField(obj, offset, val); @@ -347,7 +371,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { long val = reader.readLong(id); GridUnsafe.putLongField(obj, offset, val); @@ -377,7 +401,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { float val = reader.readFloat(id); GridUnsafe.putFloatField(obj, offset, val); @@ -407,7 +431,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { double val = reader.readDouble(id); GridUnsafe.putDoubleField(obj, offset, val); @@ -432,9 +456,7 @@ public abstract class BinaryFieldAccessor { * @param mode Mode. */ DefaultFinalClassAccessor(Field field, int id, BinaryWriteMode mode, boolean dynamic) { - super(id, mode); - - assert field != null; + super(field, id, mode); this.field = field; this.dynamic = dynamic; @@ -635,7 +657,7 @@ public abstract class BinaryFieldAccessor { } /** {@inheritDoc} */ - @Override public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { + @Override public void read0(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException { Object val = dynamic ? reader.readField(id) : readFixedType(reader); try { http://git-wip-us.apache.org/repos/asf/ignite/blob/1118c728/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java index 775f237..a0aac3f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryReaderExImpl.java @@ -35,6 +35,7 @@ import org.apache.ignite.binary.BinaryRawReader; import org.apache.ignite.binary.BinaryReader; import org.apache.ignite.internal.binary.streams.BinaryInputStream; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.internal.util.typedef.internal.S; import org.apache.ignite.internal.util.typedef.internal.SB; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -329,7 +330,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina * @throws BinaryObjectException In case of error. */ @Nullable Object unmarshalField(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? BinaryUtils.unmarshal(in, ctx, ldr, this) : null; + try { + return findFieldByName(fieldName) ? BinaryUtils.unmarshal(in, ctx, ldr, this) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -421,9 +427,29 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina return (T)obj; } + + /** + * Wraps an exception by adding the fieldName + * + * @param fieldName the name of the field, causes failure + * @param e the cause of the deserialization failure + * @return wrapping exception + */ + private BinaryObjectException wrapFieldException(String fieldName, Exception e) { + if (S.INCLUDE_SENSITIVE) + return new BinaryObjectException("Failed to read field: " + fieldName, e); + else + return new BinaryObjectException("Failed to read field.", e); + } + /** {@inheritDoc} */ @Override public byte readByte(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(BYTE) == Flag.NORMAL ? in.readByte() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(BYTE) == Flag.NORMAL ? in.readByte() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -451,7 +477,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public byte[] readByteArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readByteArray() : null; + try { + return findFieldByName(fieldName) ? this.readByteArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -479,7 +510,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public boolean readBoolean(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(BOOLEAN) == Flag.NORMAL && in.readBoolean(); + try { + return findFieldByName(fieldName) && checkFlagNoHandles(BOOLEAN) == Flag.NORMAL && in.readBoolean(); + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -507,7 +543,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public boolean[] readBooleanArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readBooleanArray() : null; + try { + return findFieldByName(fieldName) ? this.readBooleanArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -535,7 +576,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public short readShort(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(SHORT) == Flag.NORMAL ? in.readShort() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(SHORT) == Flag.NORMAL ? in.readShort() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -563,7 +609,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public short[] readShortArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readShortArray() : null; + try { + return findFieldByName(fieldName) ? this.readShortArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -591,7 +642,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public char readChar(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(CHAR) == Flag.NORMAL ? in.readChar() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(CHAR) == Flag.NORMAL ? in.readChar() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -619,7 +675,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public char[] readCharArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readCharArray() : null; + try { + return findFieldByName(fieldName) ? this.readCharArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -647,7 +708,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public int readInt(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(INT) == Flag.NORMAL ? in.readInt() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(INT) == Flag.NORMAL ? in.readInt() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -675,7 +741,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public int[] readIntArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readIntArray() : null; + try { + return findFieldByName(fieldName) ? this.readIntArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -703,7 +774,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public long readLong(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(LONG) == Flag.NORMAL ? in.readLong() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(LONG) == Flag.NORMAL ? in.readLong() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -731,7 +807,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public long[] readLongArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readLongArray() : null; + try { + return findFieldByName(fieldName) ? this.readLongArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -759,7 +840,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public float readFloat(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(FLOAT) == Flag.NORMAL ? in.readFloat() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(FLOAT) == Flag.NORMAL ? in.readFloat() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -787,7 +873,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public float[] readFloatArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readFloatArray() : null; + try { + return findFieldByName(fieldName) ? this.readFloatArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -815,7 +906,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override public double readDouble(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) && checkFlagNoHandles(DOUBLE) == Flag.NORMAL ? in.readDouble() : 0; + try { + return findFieldByName(fieldName) && checkFlagNoHandles(DOUBLE) == Flag.NORMAL ? in.readDouble() : 0; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -843,7 +939,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public double[] readDoubleArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readDoubleArray() : null; + try { + return findFieldByName(fieldName) ? this.readDoubleArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -871,7 +972,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public BigDecimal readDecimal(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readDecimal() : null; + try { + return findFieldByName(fieldName) ? this.readDecimal() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -890,7 +996,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public BigDecimal[] readDecimalArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readDecimalArray() : null; + try { + return findFieldByName(fieldName) ? this.readDecimalArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -918,7 +1029,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public String readString(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readString() : null; + try { + return findFieldByName(fieldName) ? this.readString() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -937,7 +1053,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public String[] readStringArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readStringArray() : null; + try { + return findFieldByName(fieldName) ? this.readStringArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -965,7 +1086,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public UUID readUuid(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readUuid() : null; + try { + return findFieldByName(fieldName) ? this.readUuid() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -984,7 +1110,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public UUID[] readUuidArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readUuidArray() : null; + try { + return findFieldByName(fieldName) ? this.readUuidArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1012,7 +1143,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public Date readDate(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readDate() : null; + try { + return findFieldByName(fieldName) ? this.readDate() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1031,7 +1167,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public Date[] readDateArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readDateArray() : null; + try { + return findFieldByName(fieldName) ? this.readDateArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1059,7 +1200,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public Timestamp readTimestamp(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readTimestamp() : null; + try { + return findFieldByName(fieldName) ? this.readTimestamp() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1078,7 +1224,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Override @Nullable public Timestamp[] readTimestampArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readTimestampArray() : null; + try { + return findFieldByName(fieldName) ? this.readTimestampArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1107,7 +1258,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Nullable @Override public <T> T readObject(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? (T)BinaryUtils.doReadObject(in, ctx, ldr, this) : null; + try { + return findFieldByName(fieldName) ? (T)BinaryUtils.doReadObject(in, ctx, ldr, this) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1131,7 +1287,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public Object[] readObjectArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? this.readObjectArray() : null; + try { + return findFieldByName(fieldName) ? this.readObjectArray() : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1159,7 +1320,12 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public <T extends Enum<?>> T readEnum(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? (T)readEnum0(null) : null; + try { + return findFieldByName(fieldName) ? (T)readEnum0(null) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1201,7 +1367,13 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public <T extends Enum<?>> T[] readEnumArray(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? (T[])readEnumArray0(null) : null; + + try { + return findFieldByName(fieldName) ? (T[])readEnumArray0(null) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1247,13 +1419,24 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public <T> Collection<T> readCollection(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? (Collection<T>)readCollection0(null) : null; + try { + return findFieldByName(fieldName) ? (Collection<T>)readCollection0(null) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** {@inheritDoc} */ @Nullable @Override public <T> Collection<T> readCollection(String fieldName, BinaryCollectionFactory<T> factory) throws BinaryObjectException { - return findFieldByName(fieldName) ? readCollection0(factory) : null; + + try { + return findFieldByName(fieldName) ? readCollection0(factory) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1316,13 +1499,24 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina /** {@inheritDoc} */ @Nullable @Override public <K, V> Map<K, V> readMap(String fieldName) throws BinaryObjectException { - return findFieldByName(fieldName) ? (Map<K, V>)readMap0(null) : null; + try { + return findFieldByName(fieldName) ? (Map<K, V>)readMap0(null) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** {@inheritDoc} */ @Nullable @Override public <K, V> Map<K, V> readMap(String fieldName, BinaryMapFactory<K, V> factory) throws BinaryObjectException { - return findFieldByName(fieldName) ? readMap0(factory) : null; + + try { + return findFieldByName(fieldName) ? readMap0(factory) : null; + } + catch (Exception ex) { + throw wrapFieldException(fieldName, ex); + } } /** @@ -1400,8 +1594,8 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina int pos = BinaryUtils.positionForHandle(in); - throw new BinaryObjectException("Unexpected flag value [pos=" + pos + ", expected=" + expFlag + - ", actual=" + flag + ']'); + throw new BinaryObjectException("Unexpected field type [pos=" + pos + ", expected=" + fieldFlagName(expFlag) + + ", actual=" + fieldFlagName(flag) + ']'); } /** @@ -1421,8 +1615,20 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina int pos = BinaryUtils.positionForHandle(in); - throw new BinaryObjectException("Unexpected flag value [pos=" + pos + ", expected=" + expFlag + - ", actual=" + flag + ']'); + throw new BinaryObjectException("Unexpected field type [pos=" + pos + ", expected=" + fieldFlagName(expFlag) + + ", actual=" + fieldFlagName(flag) + ']'); + } + + /** + * Gets a flag name + * + * @param flag a flag value + * @return string representation of the flag (type name, handle, else number) + */ + private String fieldFlagName(byte flag) { + String typeName = BinaryUtils.fieldTypeName(flag); + + return typeName == null ? String.valueOf(flag) : typeName; } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/1118c728/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index 1153d15..1d06417 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -347,16 +347,13 @@ public class BinaryUtils { /** * @param typeId Field type ID. - * @return Field type name. + * @return Field type name or {@code null} if unknown. */ public static String fieldTypeName(int typeId) { - assert typeId >= 0 && typeId < FIELD_TYPE_NAMES.length : typeId; - - String typeName = FIELD_TYPE_NAMES[typeId]; - - assert typeName != null : typeId; + if(typeId < 0 || typeId >= FIELD_TYPE_NAMES.length) + return null; - return typeName; + return FIELD_TYPE_NAMES[typeId]; } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/1118c728/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectExceptionSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectExceptionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectExceptionSelfTest.java new file mode 100644 index 0000000..e4be824 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectExceptionSelfTest.java @@ -0,0 +1,209 @@ +/* + * 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.ignite.internal.binary; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Date; +import java.util.Iterator; +import java.util.UUID; +import javax.cache.Cache; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.binary.BinaryBasicNameMapper; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.configuration.BinaryConfiguration; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +/** + * BinaryObjectExceptionSelfTest + */ +public class BinaryObjectExceptionSelfTest extends GridCommonAbstractTest { + /** */ + private static final String TEST_KEY = "test_key"; + + /** */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + cfg.setMarshaller(new BinaryMarshaller()); + cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(IP_FINDER)); + + cfg.setCacheConfiguration(new CacheConfiguration().setCopyOnRead(true)); + + BinaryConfiguration bcfg = new BinaryConfiguration(); + + bcfg.setNameMapper(new BinaryBasicNameMapper(false)); + + cfg.setBinaryConfiguration(bcfg); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + startGrids(2); + + awaitPartitionMapExchange(); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + } + + /** + * Test unexpected field type. + * + * @throws Exception If failed. + */ + @SuppressWarnings("WhileLoopReplaceableByForEach") + public void testUnexpectedFieldType() throws Exception { + IgniteEx grid = grid(0); + + IgniteCache<String, Value> cache = grid.cache(null); + + cache.put(TEST_KEY, new Value()); + + BinaryObjectImpl b = (BinaryObjectImpl)cache.withKeepBinary().get(TEST_KEY); + + b.deserialize(); // deserialize working + + byte[] a = b.array(); + + int unexpectedCnt = 0; + + Field[] fields = Value.class.getDeclaredFields(); + + StringBuilder sb = new StringBuilder(4 << 10); + + for (int i = b.dataStartOffset(), j = b.footerStartOffset(); i < j; ++i) { + byte old = a[i]; + + a[i] = -1; + + try { + Iterator<Cache.Entry<String, Value>> it = cache.iterator(); + + while (it.hasNext()) + it.next(); + } + catch (Exception ex) { + Throwable root = ex; + + sb.setLength(0); + + sb.append(root.getMessage()); + + while (root.getCause() != null) { + root = root.getCause(); + + sb.append(". ").append(root.getMessage()); + } + if (root instanceof BinaryObjectException && root.getMessage().startsWith("Unexpected field type")) { + log().info(sb.toString()); + + Field f = fields[unexpectedCnt]; + + Throwable t = ex; + + assertTrue(t.getMessage(), t.getMessage().contains( + "object [typeName=org.apache.ignite.internal.binary.BinaryObjectExceptionSelfTest$Value")); + + t = t.getCause(); + + assertTrue(t.getMessage(), t.getMessage().contains("field [name=" + f.getName())); + + ++unexpectedCnt; + } + else + log().info("Ignored exception: " + sb); + } + + a[i] = old; + } + + assertEquals("Fields count must match \"Unexpected field type\" exception count", fields.length, unexpectedCnt); + } + + /** */ + private enum EnumValues { + /** */ + val1, + + /** */ + val2, + + /** */ + val3; + } + + /** */ + @SuppressWarnings("unused") + private static class Value { + /** */ + public byte byteVal = 1; + + /** */ + public boolean booleanVal = true; + + /** */ + public short shortVal = 2; + + /** */ + public char charVal = 'Q'; + + /** */ + public int intVal = 3; + + /** */ + public long longVal = 4; + + /** */ + public float floatVal = 5; + + /** */ + public double doubleVal = 6; + + /** */ + public BigDecimal bigDecimal = new BigDecimal(7); + + /** */ + public String string = "QWERTY"; + + /** */ + public UUID uuid = UUID.randomUUID(); + + /** */ + public Date date = new Date(); + + /** */ + public Timestamp timestamp = new Timestamp(date.getTime() + 1000L); + + /** */ + public EnumValues enumVal = EnumValues.val2; + } +}
