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 732c4c59d3..a3919b8056 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 @@ -185,6 +185,8 @@ public class BinaryClassDescriptor { else { if (cls == BinaryEnumObjectImpl.class) mode = BinaryWriteMode.BINARY_ENUM; + else if (cls == BinaryObjectArray.class) + mode = BinaryWriteMode.OBJECT_ARR; else mode = serializer != null ? BinaryWriteMode.BINARY : BinaryUtils.mode(cls); } @@ -714,7 +716,7 @@ public class BinaryClassDescriptor { break; case OBJECT_ARR: - writer.doWriteObjectArray((Object[])obj); + writer.doWriteObjectArray(obj); break; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java index f9f7dd8232..c710b2a4fa 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java @@ -240,6 +240,7 @@ public class BinaryContext { registerPredefinedType(Timestamp[].class, GridBinaryMarshaller.TIMESTAMP_ARR); registerPredefinedType(Time[].class, GridBinaryMarshaller.TIME_ARR); registerPredefinedType(Object[].class, GridBinaryMarshaller.OBJ_ARR); + registerPredefinedType(BinaryObjectArray.class, GridBinaryMarshaller.OBJ_ARR); // Special collections. registerPredefinedType(ArrayList.class, 0); 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 4f159a3a0f..db35bc08e6 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 @@ -647,7 +647,7 @@ public abstract class BinaryFieldAccessor { break; case OBJECT_ARR: - writer.writeObjectArrayField((Object[])val); + writer.writeObjectArrayField(val); break; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java new file mode 100644 index 0000000000..216f423e34 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectArray.java @@ -0,0 +1,40 @@ +/* + * 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.io.Serializable; + +final class BinaryObjectArray implements Serializable { + private static final long serialVersionUID = 0L; + + private final int itemTypeId; + private final Object[] items; + + BinaryObjectArray(int itemTypeId, Object[] items) { + this.itemTypeId = itemTypeId; + this.items = items; + } + + public int itemTypeId() { + return itemTypeId; + } + + public Object[] items() { + return items; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java index 603275ecc6..c9e3f5383d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryRawReaderEx.java @@ -30,4 +30,11 @@ public interface BinaryRawReaderEx extends BinaryRawReader { * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ @Nullable public Object readObjectDetached() throws BinaryObjectException; + + /** + * @param deserialize {@code true} if object should be unmarshelled and then deserialized. + * @return Object. + * @throws org.apache.ignite.binary.BinaryObjectException In case of error. + */ + @Nullable public Object readObjectDetached(boolean deserialize) throws BinaryObjectException; } 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 2f0ff23105..cc3a51d351 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 @@ -1336,6 +1336,11 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina return BinaryUtils.unmarshal(in, ctx, ldr, this, true); } + /** {@inheritDoc} */ + @Nullable @Override public Object readObjectDetached(boolean deserialize) throws BinaryObjectException { + return BinaryUtils.unmarshal(in, ctx, ldr, this, true, deserialize); + } + /** {@inheritDoc} */ @Nullable @Override public Object[] readObjectArray(String fieldName) throws BinaryObjectException { try { @@ -1359,7 +1364,7 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Bina @Nullable @Override public Object[] readObjectArray() throws BinaryObjectException { switch (checkFlag(OBJ_ARR)) { case NORMAL: - return BinaryUtils.doReadObjectArray(in, ctx, ldr, this, false, true); + return (Object[])BinaryUtils.doReadObjectArray(in, ctx, ldr, this, false, true); case HANDLE: return readHandleField(); 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 8491943550..131a01537f 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 @@ -1555,6 +1555,21 @@ public class BinaryUtils { return doReadClass(in, ctx, ldr, true); } + /** + * @param in Binary input stream. + * @return Type ID specified at the input stream + * @throws BinaryObjectException If failed. + */ + public static int doReadTypeId(BinaryInputStream in) + throws BinaryObjectException { + int typeId = in.readInt(); + + if (typeId == GridBinaryMarshaller.UNREGISTERED_TYPE_ID) + doReadClassName(in); + + return typeId; + } + /** * @param in Binary input stream. * @param ctx Binary context. @@ -1819,12 +1834,25 @@ public class BinaryUtils { return unmarshal(in, ctx, ldr, handles, false); } + /** + * @return Unmarshalled value. + * @throws BinaryObjectException In case of error. + */ + @Nullable public static Object unmarshal( + BinaryInputStream in, + BinaryContext ctx, + ClassLoader ldr, + BinaryReaderHandlesHolder handles, + boolean detach) throws BinaryObjectException { + return unmarshal(in, ctx, ldr, handles, detach, false); + } + /** * @return Unmarshalled value. * @throws BinaryObjectException In case of error. */ @Nullable public static Object unmarshal(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, - BinaryReaderHandlesHolder handles, boolean detach) throws BinaryObjectException { + BinaryReaderHandlesHolder handles, boolean detach, boolean deserialize) throws BinaryObjectException { int start = in.position(); byte flag = in.readByte(); @@ -1876,7 +1904,7 @@ public class BinaryUtils { handles.setHandle(po, start); - return po; + return deserialize ? po.deserialize() : po; } case GridBinaryMarshaller.BYTE: @@ -1964,13 +1992,13 @@ public class BinaryUtils { return doReadTimeArray(in); case GridBinaryMarshaller.OBJ_ARR: - return doReadObjectArray(in, ctx, ldr, handles, detach, false); + return doReadObjectArray(in, ctx, ldr, handles, detach, deserialize); case GridBinaryMarshaller.COL: - return doReadCollection(in, ctx, ldr, handles, detach, false, null); + return doReadCollection(in, ctx, ldr, handles, detach, deserialize, null); case GridBinaryMarshaller.MAP: - return doReadMap(in, ctx, ldr, handles, detach, false, null); + return doReadMap(in, ctx, ldr, handles, detach, deserialize, null); case GridBinaryMarshaller.BINARY_OBJ: return doReadBinaryObject(in, ctx, detach); @@ -2008,11 +2036,17 @@ public class BinaryUtils { * @return Value. * @throws BinaryObjectException In case of error. */ - public static Object[] doReadObjectArray(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, + public static Object doReadObjectArray(BinaryInputStream in, BinaryContext ctx, ClassLoader ldr, BinaryReaderHandlesHolder handles, boolean detach, boolean deserialize) throws BinaryObjectException { int hPos = positionForHandle(in); - Class compType = doReadClass(in, ctx, ldr, deserialize); + Class compType = null; + int compTypeId = 0; + + if (deserialize) + compType = doReadClass(in, ctx, ldr, deserialize); + else + compTypeId = doReadTypeId(in); int len = in.readInt(); @@ -2023,7 +2057,11 @@ public class BinaryUtils { for (int i = 0; i < len; i++) arr[i] = deserializeOrUnmarshal(in, ctx, ldr, handles, detach, deserialize); - return arr; + boolean keepCompTypeId = !deserialize + && compTypeId != GridBinaryMarshaller.OBJECT + && compTypeId != GridBinaryMarshaller.UNREGISTERED_TYPE_ID; + + return keepCompTypeId ? new BinaryObjectArray(compTypeId, arr) : arr; } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java index db7833e182..199039fa33 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryWriterExImpl.java @@ -745,32 +745,38 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje * @param val Array of objects. * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ - void doWriteObjectArray(@Nullable Object[] val) throws BinaryObjectException { + void doWriteObjectArray(@Nullable Object val) throws BinaryObjectException { if (val == null) out.writeByte(GridBinaryMarshaller.NULL); else { - if (tryWriteAsHandle(val)) + boolean isBinary = val instanceof BinaryObjectArray; + + Object[] arr = isBinary ? ((BinaryObjectArray)val).items() : (Object[])val; + + if (tryWriteAsHandle(arr)) return; BinaryClassDescriptor desc = ctx.registerClass( - val.getClass().getComponentType(), + arr.getClass().getComponentType(), true, failIfUnregistered); out.unsafeEnsure(1 + 4); out.unsafeWriteByte(GridBinaryMarshaller.OBJ_ARR); - if (desc.registered()) + if (isBinary) + out.unsafeWriteInt(((BinaryObjectArray)val).itemTypeId()); + else if (desc.registered()) out.unsafeWriteInt(desc.typeId()); else { out.unsafeWriteInt(GridBinaryMarshaller.UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); + doWriteString(arr.getClass().getComponentType().getName()); } - out.writeInt(val.length); + out.writeInt(arr.length); - for (Object obj : val) + for (Object obj : arr) doWriteObject(obj); } } @@ -1296,7 +1302,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje * @param val Value. * @throws org.apache.ignite.binary.BinaryObjectException In case of error. */ - void writeObjectArrayField(@Nullable Object[] val) throws BinaryObjectException { + void writeObjectArrayField(@Nullable Object val) throws BinaryObjectException { doWriteObjectArray(val); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java index 8e67cab2d0..0fb47b945e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/services/PlatformServices.java @@ -274,18 +274,20 @@ public class PlatformServices extends PlatformAbstractTarget { String mthdName = reader.readString(); Object[] args; + ServiceProxyHolder svcProxy = (ServiceProxyHolder)arg; if (reader.readBoolean()) { args = new Object[reader.readInt()]; + boolean keepBinary = srvKeepBinary || svcProxy.isPlatformService(); for (int i = 0; i < args.length; i++) - args[i] = reader.readObjectDetached(); + args[i] = reader.readObjectDetached(!keepBinary); } else args = null; try { - Object result = ((ServiceProxyHolder)arg).invoke(mthdName, srvKeepBinary, args); + Object result = svcProxy.invoke(mthdName, srvKeepBinary, args); PlatformUtils.writeInvocationResult(writer, result, null); } @@ -571,6 +573,14 @@ public class PlatformServices extends PlatformAbstractTarget { serviceClass = clazz; } + /** + * @return {@code true} if the target service is a {@link PlatformService} and {@code false} if the target + * service is a native Java service. + */ + public boolean isPlatformService() { + return PlatformService.class.isAssignableFrom(serviceClass); + } + /** * Invokes the proxy. * @@ -588,10 +598,6 @@ public class PlatformServices extends PlatformAbstractTarget { else { assert proxy instanceof GridServiceProxy; - // Deserialize arguments for Java service when not in binary mode - if (!srvKeepBinary) - args = PlatformUtils.unwrapBinariesInArray(args); - Method mtd = getMethod(serviceClass, mthdName, args); // Convert Object[] to T[] when required: