http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java deleted file mode 100644 index f5df6d6..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/portable/GridPortableWriterExImpl.java +++ /dev/null @@ -1,1770 +0,0 @@ -/* - * 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.portable; - -import org.apache.ignite.*; -import org.apache.ignite.internal.portable.streams.*; -import org.apache.ignite.internal.processors.portable.*; -import org.apache.ignite.internal.util.typedef.internal.*; -import org.apache.ignite.portable.*; - -import org.jetbrains.annotations.*; - -import java.io.*; -import java.lang.reflect.*; -import java.math.*; -import java.sql.*; -import java.util.*; -import java.util.Date; -import java.util.concurrent.*; - -import static java.nio.charset.StandardCharsets.*; -import static org.apache.ignite.internal.portable.GridPortableMarshaller.*; - - /** - * Portable writer implementation. - */ -public class GridPortableWriterExImpl implements PortableWriter, GridPortableRawWriterEx, ObjectOutput { - /** Length: integer. */ - private static final int LEN_INT = 4; - - /** */ - private static final int INIT_CAP = 1024; - - /** */ - private static final ConcurrentHashMap<Class<?>, Boolean> useOptMarshCache = new ConcurrentHashMap<>(); - - /** */ - private final GridPortableContext ctx; - - /** */ - private final WriterContext wCtx; - - /** */ - private final int start; - - /** */ - private int mark; - - /** */ - private Class<?> cls; - - /** */ - private int typeId; - - /** */ - private boolean allowFields = true; - - /** */ - private boolean metaEnabled; - - /** */ - private int metaHashSum; - - /** - * @param ctx Context. - * @param off Start offset. - */ - GridPortableWriterExImpl(GridPortableContext ctx, int off) { - this.ctx = ctx; - - GridPortableOutputStream out = new GridPortableHeapOutputStream(off + INIT_CAP); - - out.position(off); - - wCtx = new WriterContext(out, null); - - start = off; - } - - /** - * @param ctx Context. - * @param out Output stream. - * @param off Start offset. - */ - GridPortableWriterExImpl(GridPortableContext ctx, GridPortableOutputStream out, int off) { - this.ctx = ctx; - - wCtx = new WriterContext(out, null); - - start = off; - } - - /** - * @param ctx Context. - * @param off Start offset. - * @param typeId Type ID. - */ - GridPortableWriterExImpl(GridPortableContext ctx, int off, int typeId, boolean metaEnabled) { - this(ctx, off); - - this.typeId = typeId; - - this.metaEnabled = metaEnabled; - } - - /** - * @param ctx Context. - * @param wCtx Writer context. - */ - private GridPortableWriterExImpl(GridPortableContext ctx, WriterContext wCtx) { - this.ctx = ctx; - this.wCtx = wCtx; - - start = wCtx.out.position(); - } - - /** - * Close the writer releasing resources if necessary. - */ - @Override public void close() { - wCtx.out.close(); - } - - /** - * @return Meta data hash sum or {@code null} if meta data is disabled. - */ - @Nullable Integer metaDataHashSum() { - return metaEnabled ? metaHashSum : null; - } - - /** - * @param obj Object. - * @param detached Detached or not. - * @throws PortableException In case of error. - */ - void marshal(Object obj, boolean detached) throws PortableException { - assert obj != null; - - if (useOptimizedMarshaller(obj)) { - writeByte(OPTM_MARSH); - - try { - byte[] arr = ctx.optimizedMarsh().marshal(obj); - - writeInt(arr.length); - - write(arr); - } - catch (IgniteCheckedException e) { - throw new PortableException("Failed to marshal object with optimized marshaller: " + obj, e); - } - - return; - } - - cls = obj.getClass(); - - GridPortableClassDescriptor desc = ctx.descriptorForClass(cls); - - if (desc == null) - throw new PortableException("Object is not portable: [class=" + cls + ']'); - - if (desc.excluded()) { - doWriteByte(NULL); - return; - } - - if (desc.getWriteReplaceMethod() != null) { - Object replace; - - try { - replace = desc.getWriteReplaceMethod().invoke(obj); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - if (e.getTargetException() instanceof PortableException) - throw (PortableException)e.getTargetException(); - - throw new PortableException("Failed to execute writeReplace() method on " + obj, e); - } - - if (replace == null) { - doWriteByte(NULL); - return; - } - - if (cls != replace.getClass()) { - cls = replace.getClass(); - - desc = ctx.descriptorForClass(cls); - - if (desc == null) - throw new PortableException("Object is not portable: [class=" + cls + ']'); - } - - obj = replace; - } - - typeId = desc.typeId(); - - metaEnabled = ctx.isMetaDataEnabled(typeId); - - if (detached) - wCtx.resetHandles(); - - desc.write(obj, this); - } - - /** - * Determines whether to use {@link org.apache.ignite.marshaller.optimized.OptimizedMarshaller} for serialization - * or not. - * - * @param obj Object to serialize. - * @return {@code true} if to use, {@code false} otherwise. - */ - private boolean useOptimizedMarshaller(Object obj) { - Class<?> cls = obj.getClass(); - - Boolean use = useOptMarshCache.get(cls); - - if (use != null) - return use; - - if (ctx.isPredefinedClass(cls)) - use = false; - else { - try { - Method writeObj = cls.getDeclaredMethod("writeObject", ObjectOutputStream.class); - Method readObj = cls.getDeclaredMethod("readObject", ObjectInputStream.class); - - if (!Modifier.isStatic(writeObj.getModifiers()) && !Modifier.isStatic(readObj.getModifiers()) && - writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) - use = true; - else - use = false; - - } catch (NoSuchMethodException e) { - use = false; - } - } - - useOptMarshCache.putIfAbsent(cls, use); - - return use; - } - - /** - * @param obj Object. - * @return Handle. - */ - int handle(Object obj) { - assert obj != null; - - return wCtx.handle(obj); - } - - /** - * @return Array. - */ - byte[] array() { - return wCtx.out.arrayCopy(); - } - - /** - * @return Output stream. - */ - GridPortableOutputStream outputStream() { - return wCtx.out; - } - - /** - * @return Stream current position. - */ - int position() { - return wCtx.out.position(); - } - - /** - * Sets new position. - * - * @param pos Position. - */ - void position(int pos) { - wCtx.out.position(pos); - } - - /** - * @param bytes Number of bytes to reserve. - * @return Offset. - */ - int reserve(int bytes) { - int pos = wCtx.out.position(); - - wCtx.out.position(pos + bytes); - - return pos; - } - - /** - * @param bytes Number of bytes to reserve. - * @return Offset. - */ - int reserveAndMark(int bytes) { - int off0 = reserve(bytes); - - mark = wCtx.out.position(); - - return off0; - } - - /** - * @param off Offset. - */ - void writeDelta(int off) { - wCtx.out.writeInt(off, wCtx.out.position() - mark); - } - - /** - * - */ - void writeLength() { - wCtx.out.writeInt(start + TOTAL_LEN_POS, wCtx.out.position() - start); - } - - /** - * - */ - void writeRawOffsetIfNeeded() { - if (allowFields) - wCtx.out.writeInt(start + RAW_DATA_OFF_POS, wCtx.out.position() - start); - } - - /** - * @param val Byte array. - */ - public void write(byte[] val) { - assert val != null; - - wCtx.out.writeByteArray(val); - } - - /** - * @param val Byte array. - * @param off Offset. - * @param len Length. - */ - public void write(byte[] val, int off, int len) { - assert val != null; - - wCtx.out.write(val, off, len); - } - - /** - * @param val Value. - */ - void doWriteByte(byte val) { - wCtx.out.writeByte(val); - } - - /** - * @param val Value. - */ - void doWriteShort(short val) { - wCtx.out.writeShort(val); - } - - /** - * @param val Value. - */ - void doWriteInt(int val) { - wCtx.out.writeInt(val); - } - - /** - * @param val Value. - */ - void doWriteLong(long val) { - wCtx.out.writeLong(val); - } - - /** - * @param val Value. - */ - void doWriteFloat(float val) { - wCtx.out.writeFloat(val); - } - - /** - * @param val Value. - */ - void doWriteDouble(double val) { - wCtx.out.writeDouble(val); - } - - /** - * @param val Value. - */ - void doWriteChar(char val) { - wCtx.out.writeChar(val); - } - - /** - * @param val Value. - */ - void doWriteBoolean(boolean val) { - wCtx.out.writeBoolean(val); - } - - /** - * @param val String value. - */ - void doWriteDecimal(@Nullable BigDecimal val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DECIMAL); - - BigInteger intVal = val.unscaledValue(); - - if (intVal.signum() == -1) { - intVal = intVal.negate(); - - wCtx.out.writeInt(val.scale() | 0x80000000); - } - else - wCtx.out.writeInt(val.scale()); - - byte[] vals = intVal.toByteArray(); - - wCtx.out.writeInt(vals.length); - wCtx.out.writeByteArray(vals); - } - } - - /** - * @param val String value. - */ - void doWriteString(@Nullable String val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(STRING); - - if (ctx.isConvertString()) { - doWriteBoolean(true); - - byte[] strArr = val.getBytes(UTF_8); - - doWriteInt(strArr.length); - - wCtx.out.writeByteArray(strArr); - } - else { - doWriteBoolean(false); - - char[] strArr = val.toCharArray(); - - doWriteInt(strArr.length); - - wCtx.out.writeCharArray(strArr); - } - } - } - - /** - * @param uuid UUID. - */ - void doWriteUuid(@Nullable UUID uuid) { - if (uuid == null) - doWriteByte(NULL); - else { - doWriteByte(UUID); - doWriteLong(uuid.getMostSignificantBits()); - doWriteLong(uuid.getLeastSignificantBits()); - } - } - - /** - * @param date Date. - */ - void doWriteDate(@Nullable Date date) { - if (date == null) - doWriteByte(NULL); - else { - doWriteByte(DATE); - doWriteLong(date.getTime()); - doWriteInt(0); - } - } - - /** - * @param ts Timestamp. - */ - void doWriteTimestamp(@Nullable Timestamp ts) { - if (ts == null) - doWriteByte(NULL); - else { - doWriteByte(DATE); - doWriteLong(ts.getTime()); - doWriteInt(ts.getNanos() % 1000000); - } - } - - /** - * @param obj Object. - * @param detached Detached or not. - * @throws PortableException In case of error. - */ - void doWriteObject(@Nullable Object obj, boolean detached) throws PortableException { - if (obj == null) - doWriteByte(NULL); - else { - WriterContext wCtx = detached ? new WriterContext(this.wCtx.out, this.wCtx.handles) : this.wCtx; - - GridPortableWriterExImpl writer = new GridPortableWriterExImpl(ctx, wCtx); - - writer.marshal(obj, detached); - - if (detached) - this.wCtx.out = wCtx.out; - } - } - - /** - * @param val Byte array. - */ - void doWriteByteArray(@Nullable byte[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BYTE_ARR); - doWriteInt(val.length); - - wCtx.out.writeByteArray(val); - } - } - - /** - * @param val Short array. - */ - void doWriteShortArray(@Nullable short[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(SHORT_ARR); - doWriteInt(val.length); - - wCtx.out.writeShortArray(val); - } - } - - /** - * @param val Integer array. - */ - void doWriteIntArray(@Nullable int[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(INT_ARR); - doWriteInt(val.length); - - wCtx.out.writeIntArray(val); - } - } - - /** - * @param val Long array. - */ - void doWriteLongArray(@Nullable long[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(LONG_ARR); - doWriteInt(val.length); - - wCtx.out.writeLongArray(val); - } - } - - /** - * @param val Float array. - */ - void doWriteFloatArray(@Nullable float[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(FLOAT_ARR); - doWriteInt(val.length); - - wCtx.out.writeFloatArray(val); - } - } - - /** - * @param val Double array. - */ - void doWriteDoubleArray(@Nullable double[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DOUBLE_ARR); - doWriteInt(val.length); - - wCtx.out.writeDoubleArray(val); - } - } - - /** - * @param val Char array. - */ - void doWriteCharArray(@Nullable char[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(CHAR_ARR); - doWriteInt(val.length); - - wCtx.out.writeCharArray(val); - } - } - - /** - * @param val Boolean array. - */ - void doWriteBooleanArray(@Nullable boolean[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BOOLEAN_ARR); - doWriteInt(val.length); - - wCtx.out.writeBooleanArray(val); - } - } - - /** - * @param val Array of strings. - */ - void doWriteDecimalArray(@Nullable BigDecimal[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DECIMAL_ARR); - doWriteInt(val.length); - - for (BigDecimal str : val) - doWriteDecimal(str); - } - } - - /** - * @param val Array of strings. - */ - void doWriteStringArray(@Nullable String[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(STRING_ARR); - doWriteInt(val.length); - - for (String str : val) - doWriteString(str); - } - } - - /** - * @param val Array of UUIDs. - */ - void doWriteUuidArray(@Nullable UUID[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(UUID_ARR); - doWriteInt(val.length); - - for (UUID uuid : val) - doWriteUuid(uuid); - } - } - - /** - * @param val Array of dates. - */ - void doWriteDateArray(@Nullable Date[] val) { - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DATE_ARR); - doWriteInt(val.length); - - for (Date date : val) - doWriteDate(date); - } - } - - /** - * @param val Array of objects. - * @throws PortableException In case of error. - */ - void doWriteObjectArray(@Nullable Object[] val) throws PortableException { - if (val == null) - doWriteByte(NULL); - else { - GridPortableContext.Type type = ctx.typeId(val.getClass().getComponentType()); - - doWriteByte(OBJ_ARR); - - if (type.registered()) - doWriteInt(type.id()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); - } - - doWriteInt(val.length); - - for (Object obj : val) - doWriteObject(obj, false); - } - } - - /** - * @param col Collection. - * @throws PortableException In case of error. - */ - void doWriteCollection(@Nullable Collection<?> col) throws PortableException { - if (col == null) - doWriteByte(NULL); - else { - doWriteByte(COL); - doWriteInt(col.size()); - doWriteByte(ctx.collectionType(col.getClass())); - - for (Object obj : col) - doWriteObject(obj, false); - } - } - - /** - * @param map Map. - * @throws PortableException In case of error. - */ - void doWriteMap(@Nullable Map<?, ?> map) throws PortableException { - if (map == null) - doWriteByte(NULL); - else { - doWriteByte(MAP); - doWriteInt(map.size()); - doWriteByte(ctx.mapType(map.getClass())); - - for (Map.Entry<?, ?> e : map.entrySet()) { - doWriteObject(e.getKey(), false); - doWriteObject(e.getValue(), false); - } - } - } - - /** - * @param e Map entry. - * @throws PortableException In case of error. - */ - void doWriteMapEntry(@Nullable Map.Entry<?, ?> e) throws PortableException { - if (e == null) - doWriteByte(NULL); - else { - doWriteByte(MAP_ENTRY); - doWriteObject(e.getKey(), false); - doWriteObject(e.getValue(), false); - } - } - - /** - * @param val Value. - */ - void doWriteEnum(@Nullable Enum<?> val) { - if (val == null) - doWriteByte(NULL); - else { - GridPortableContext.Type type = ctx.typeId(val.getClass()); - - doWriteByte(ENUM); - - if (type.registered()) - doWriteInt(type.id()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getName()); - } - - doWriteInt(val.ordinal()); - } - } - - /** - * @param val Array. - */ - void doWriteEnumArray(@Nullable Object[] val) { - assert val == null || val.getClass().getComponentType().isEnum(); - - if (val == null) - doWriteByte(NULL); - else { - GridPortableContext.Type type = ctx.typeId(val.getClass().getComponentType()); - - doWriteByte(ENUM_ARR); - - if (type.registered()) - doWriteInt(type.id()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getComponentType().getName()); - } - - doWriteInt(val.length); - - // TODO: Denis: Redundant data for each element of the array. - for (Object o : val) - doWriteEnum((Enum<?>)o); - } - } - - /** - * @param val Class. - */ - void doWriteClass(@Nullable Class val) { - if (val == null) - doWriteByte(NULL); - else { - GridPortableContext.Type type = ctx.typeId(val); - - doWriteByte(CLASS); - - if (type.registered()) - doWriteInt(type.id()); - else { - doWriteInt(UNREGISTERED_TYPE_ID); - doWriteString(val.getClass().getName()); - } - } - } - - /** - * @param po Portable object. - */ - void doWritePortableObject(@Nullable GridPortableObjectImpl po) { - if (po == null) - doWriteByte(NULL); - else { - doWriteByte(PORTABLE_OBJ); - - byte[] poArr = po.array(); - - doWriteInt(poArr.length); - - wCtx.out.writeByteArray(poArr); - - doWriteInt(po.start()); - } - } - - /** - * @param val Value. - */ - void writeByteField(@Nullable Byte val) { - doWriteInt(val != null ? 2 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BYTE); - doWriteByte(val); - } - } - - /** - * @param val Class. - */ - void writeClassField(@Nullable Class val) { - int lenPos = reserveAndMark(4); - - doWriteClass(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeShortField(@Nullable Short val) { - doWriteInt(val != null ? 3 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(SHORT); - doWriteShort(val); - } - } - - /** - * @param val Value. - */ - void writeIntField(@Nullable Integer val) { - doWriteInt(val != null ? 5 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(INT); - doWriteInt(val); - } - } - - /** - * @param val Value. - */ - void writeLongField(@Nullable Long val) { - doWriteInt(val != null ? 9 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(LONG); - doWriteLong(val); - } - } - - /** - * @param val Value. - */ - void writeFloatField(@Nullable Float val) { - doWriteInt(val != null ? 5 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(FLOAT); - doWriteFloat(val); - } - } - - /** - * @param val Value. - */ - void writeDoubleField(@Nullable Double val) { - doWriteInt(val != null ? 9 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(DOUBLE); - doWriteDouble(val); - } - } - - /** - * @param val Value. - */ - void writeCharField(@Nullable Character val) { - doWriteInt(val != null ? 3 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(CHAR); - doWriteChar(val); - } - } - - /** - * @param val Value. - */ - void writeBooleanField(@Nullable Boolean val) { - doWriteInt(val != null ? 2 : 1); - - if (val == null) - doWriteByte(NULL); - else { - doWriteByte(BOOLEAN); - doWriteBoolean(val); - } - } - - /** - * @param val Value. - */ - void writeDecimalField(@Nullable BigDecimal val) { - int lenPos = reserveAndMark(4); - - doWriteDecimal(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeStringField(@Nullable String val) { - int lenPos = reserveAndMark(4); - - doWriteString(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeUuidField(@Nullable UUID val) { - doWriteInt(val != null ? 17 : 1); - doWriteUuid(val); - } - - /** - * @param val Value. - */ - void writeDateField(@Nullable Date val) { - doWriteInt(val != null ? 13 : 1); - doWriteDate(val); - } - - /** - * @param val Value. - */ - void writeTimestampField(@Nullable Timestamp val) { - doWriteInt(val != null ? 13 : 1); - doWriteTimestamp(val); - } - - /** - * @param obj Object. - * @throws PortableException In case of error. - */ - void writeObjectField(@Nullable Object obj) throws PortableException { - int lenPos = reserveAndMark(4); - - doWriteObject(obj, false); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeByteArrayField(@Nullable byte[] val) { - doWriteInt(val != null ? 5 + val.length : 1); - doWriteByteArray(val); - } - - /** - * @param val Value. - */ - void writeShortArrayField(@Nullable short[] val) { - doWriteInt(val != null ? 5 + (val.length << 1) : 1); - doWriteShortArray(val); - } - - /** - * @param val Value. - */ - void writeIntArrayField(@Nullable int[] val) { - doWriteInt(val != null ? 5 + (val.length << 2) : 1); - doWriteIntArray(val); - } - - /** - * @param val Value. - */ - void writeLongArrayField(@Nullable long[] val) { - doWriteInt(val != null ? 5 + (val.length << 3) : 1); - doWriteLongArray(val); - } - - /** - * @param val Value. - */ - void writeFloatArrayField(@Nullable float[] val) { - doWriteInt(val != null ? 5 + (val.length << 2) : 1); - doWriteFloatArray(val); - } - - /** - * @param val Value. - */ - void writeDoubleArrayField(@Nullable double[] val) { - doWriteInt(val != null ? 5 + (val.length << 3) : 1); - doWriteDoubleArray(val); - } - - /** - * @param val Value. - */ - void writeCharArrayField(@Nullable char[] val) { - doWriteInt(val != null ? 5 + (val.length << 1) : 1); - doWriteCharArray(val); - } - - /** - * @param val Value. - */ - void writeBooleanArrayField(@Nullable boolean[] val) { - doWriteInt(val != null ? 5 + val.length : 1); - doWriteBooleanArray(val); - } - - /** - * @param val Value. - */ - void writeDecimalArrayField(@Nullable BigDecimal[] val) { - int lenPos = reserveAndMark(4); - - doWriteDecimalArray(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeStringArrayField(@Nullable String[] val) { - int lenPos = reserveAndMark(4); - - doWriteStringArray(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeUuidArrayField(@Nullable UUID[] val) { - int lenPos = reserveAndMark(4); - - doWriteUuidArray(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeDateArrayField(@Nullable Date[] val) { - int lenPos = reserveAndMark(4); - - doWriteDateArray(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - * @throws PortableException In case of error. - */ - void writeObjectArrayField(@Nullable Object[] val) throws PortableException { - int lenPos = reserveAndMark(4); - - doWriteObjectArray(val); - - writeDelta(lenPos); - } - - /** - * @param col Collection. - * @throws PortableException In case of error. - */ - void writeCollectionField(@Nullable Collection<?> col) throws PortableException { - int lenPos = reserveAndMark(4); - - doWriteCollection(col); - - writeDelta(lenPos); - } - - /** - * @param map Map. - * @throws PortableException In case of error. - */ - void writeMapField(@Nullable Map<?, ?> map) throws PortableException { - int lenPos = reserveAndMark(4); - - doWriteMap(map); - - writeDelta(lenPos); - } - - /** - * @param e Map entry. - * @throws PortableException In case of error. - */ - void writeMapEntryField(@Nullable Map.Entry<?, ?> e) throws PortableException { - int lenPos = reserveAndMark(4); - - doWriteMapEntry(e); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeEnumField(@Nullable Enum<?> val) { - int lenPos = reserveAndMark(4); - - doWriteEnum(val); - - writeDelta(lenPos); - } - - /** - * @param val Value. - */ - void writeEnumArrayField(@Nullable Object[] val) { - int lenPos = reserveAndMark(4); - - doWriteEnumArray(val); - - writeDelta(lenPos); - } - - /** - * @param po Portable object. - * @throws PortableException In case of error. - */ - void writePortableObjectField(@Nullable GridPortableObjectImpl po) throws PortableException { - int lenPos = reserveAndMark(4); - - doWritePortableObject(po); - - writeDelta(lenPos); - } - - /** {@inheritDoc} */ - @Override public void writeByte(String fieldName, byte val) throws PortableException { - writeFieldId(fieldName, BYTE); - writeByteField(val); - } - - /** {@inheritDoc} */ - @Override public void writeByte(byte val) throws PortableException { - doWriteByte(val); - } - - /** {@inheritDoc} */ - @Override public void writeShort(String fieldName, short val) throws PortableException { - writeFieldId(fieldName, SHORT); - writeShortField(val); - } - - /** {@inheritDoc} */ - @Override public void writeShort(short val) throws PortableException { - doWriteShort(val); - } - - /** {@inheritDoc} */ - @Override public void writeInt(String fieldName, int val) throws PortableException { - writeFieldId(fieldName, INT); - writeIntField(val); - } - - /** {@inheritDoc} */ - @Override public void writeInt(int val) throws PortableException { - doWriteInt(val); - } - - /** {@inheritDoc} */ - @Override public void writeLong(String fieldName, long val) throws PortableException { - writeFieldId(fieldName, LONG); - writeLongField(val); - } - - /** {@inheritDoc} */ - @Override public void writeLong(long val) throws PortableException { - doWriteLong(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloat(String fieldName, float val) throws PortableException { - writeFieldId(fieldName, FLOAT); - writeFloatField(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloat(float val) throws PortableException { - doWriteFloat(val); - } - - /** {@inheritDoc} */ - @Override public void writeDouble(String fieldName, double val) throws PortableException { - writeFieldId(fieldName, DOUBLE); - writeDoubleField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDouble(double val) throws PortableException { - doWriteDouble(val); - } - - /** {@inheritDoc} */ - @Override public void writeChar(String fieldName, char val) throws PortableException { - writeFieldId(fieldName, CHAR); - writeCharField(val); - } - - /** {@inheritDoc} */ - @Override public void writeChar(char val) throws PortableException { - doWriteChar(val); - } - - /** {@inheritDoc} */ - @Override public void writeBoolean(String fieldName, boolean val) throws PortableException { - writeFieldId(fieldName, BOOLEAN); - writeBooleanField(val); - } - - /** {@inheritDoc} */ - @Override public void writeBoolean(boolean val) throws PortableException { - doWriteBoolean(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimal(String fieldName, @Nullable BigDecimal val) throws PortableException { - writeFieldId(fieldName, DECIMAL); - writeDecimalField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimal(@Nullable BigDecimal val) throws PortableException { - doWriteDecimal(val); - } - - /** {@inheritDoc} */ - @Override public void writeString(String fieldName, @Nullable String val) throws PortableException { - writeFieldId(fieldName, STRING); - writeStringField(val); - } - - /** {@inheritDoc} */ - @Override public void writeString(@Nullable String val) throws PortableException { - doWriteString(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuid(String fieldName, @Nullable UUID val) throws PortableException { - writeFieldId(fieldName, UUID); - writeUuidField(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuid(@Nullable UUID val) throws PortableException { - doWriteUuid(val); - } - - /** {@inheritDoc} */ - @Override public void writeDate(String fieldName, @Nullable Date val) throws PortableException { - writeFieldId(fieldName, DATE); - writeDateField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDate(@Nullable Date val) throws PortableException { - doWriteDate(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestamp(String fieldName, @Nullable Timestamp val) throws PortableException { - writeFieldId(fieldName, DATE); - writeTimestampField(val); - } - - /** {@inheritDoc} */ - @Override public void writeTimestamp(@Nullable Timestamp val) throws PortableException { - doWriteTimestamp(val); - } - - /** {@inheritDoc} */ - @Override public void writeObject(String fieldName, @Nullable Object obj) throws PortableException { - writeFieldId(fieldName, OBJ); - writeObjectField(obj); - } - - /** {@inheritDoc} */ - @Override public void writeObject(@Nullable Object obj) throws PortableException { - doWriteObject(obj, false); - } - - /** {@inheritDoc} */ - @Override public void writeObjectDetached(@Nullable Object obj) throws PortableException { - doWriteObject(obj, true); - } - - /** {@inheritDoc} */ - @Override public void writeByteArray(String fieldName, @Nullable byte[] val) throws PortableException { - writeFieldId(fieldName, BYTE_ARR); - writeByteArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeByteArray(@Nullable byte[] val) throws PortableException { - doWriteByteArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeShortArray(String fieldName, @Nullable short[] val) throws PortableException { - writeFieldId(fieldName, SHORT_ARR); - writeShortArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeShortArray(@Nullable short[] val) throws PortableException { - doWriteShortArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeIntArray(String fieldName, @Nullable int[] val) throws PortableException { - writeFieldId(fieldName, INT_ARR); - writeIntArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeIntArray(@Nullable int[] val) throws PortableException { - doWriteIntArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeLongArray(String fieldName, @Nullable long[] val) throws PortableException { - writeFieldId(fieldName, LONG_ARR); - writeLongArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeLongArray(@Nullable long[] val) throws PortableException { - doWriteLongArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloatArray(String fieldName, @Nullable float[] val) throws PortableException { - writeFieldId(fieldName, FLOAT_ARR); - writeFloatArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeFloatArray(@Nullable float[] val) throws PortableException { - doWriteFloatArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDoubleArray(String fieldName, @Nullable double[] val) - throws PortableException { - writeFieldId(fieldName, DOUBLE_ARR); - writeDoubleArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDoubleArray(@Nullable double[] val) throws PortableException { - doWriteDoubleArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeCharArray(String fieldName, @Nullable char[] val) throws PortableException { - writeFieldId(fieldName, CHAR_ARR); - writeCharArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeCharArray(@Nullable char[] val) throws PortableException { - doWriteCharArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeBooleanArray(String fieldName, @Nullable boolean[] val) - throws PortableException { - writeFieldId(fieldName, BOOLEAN_ARR); - writeBooleanArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeBooleanArray(@Nullable boolean[] val) throws PortableException { - doWriteBooleanArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimalArray(String fieldName, @Nullable BigDecimal[] val) - throws PortableException { - writeFieldId(fieldName, DECIMAL_ARR); - writeDecimalArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDecimalArray(@Nullable BigDecimal[] val) throws PortableException { - doWriteDecimalArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeStringArray(String fieldName, @Nullable String[] val) - throws PortableException { - writeFieldId(fieldName, STRING_ARR); - writeStringArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeStringArray(@Nullable String[] val) throws PortableException { - doWriteStringArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuidArray(String fieldName, @Nullable UUID[] val) throws PortableException { - writeFieldId(fieldName, UUID_ARR); - writeUuidArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeUuidArray(@Nullable UUID[] val) throws PortableException { - doWriteUuidArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeDateArray(String fieldName, @Nullable Date[] val) throws PortableException { - writeFieldId(fieldName, DATE_ARR); - writeDateArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeDateArray(@Nullable Date[] val) throws PortableException { - doWriteDateArray(val); - } - - /** {@inheritDoc} */ - @Override public void writeObjectArray(String fieldName, @Nullable Object[] val) throws PortableException { - writeFieldId(fieldName, OBJ_ARR); - writeObjectArrayField(val); - } - - /** {@inheritDoc} */ - @Override public void writeObjectArray(@Nullable Object[] val) throws PortableException { - doWriteObjectArray(val); - } - - /** {@inheritDoc} */ - @Override public <T> void writeCollection(String fieldName, @Nullable Collection<T> col) - throws PortableException { - writeFieldId(fieldName, COL); - writeCollectionField(col); - } - - /** {@inheritDoc} */ - @Override public <T> void writeCollection(@Nullable Collection<T> col) throws PortableException { - doWriteCollection(col); - } - - /** {@inheritDoc} */ - @Override public <K, V> void writeMap(String fieldName, @Nullable Map<K, V> map) - throws PortableException { - writeFieldId(fieldName, MAP); - writeMapField(map); - } - - /** {@inheritDoc} */ - @Override public <K, V> void writeMap(@Nullable Map<K, V> map) throws PortableException { - doWriteMap(map); - } - - /** {@inheritDoc} */ - @Override public <T extends Enum<?>> void writeEnum(String fieldName, T val) throws PortableException { - writeFieldId(fieldName, ENUM); - writeEnumField(val); - } - - /** {@inheritDoc} */ - @Override public <T extends Enum<?>> void writeEnum(T val) throws PortableException { - doWriteEnum(val); - } - - /** {@inheritDoc} */ - @Override public <T extends Enum<?>> void writeEnumArray(String fieldName, T[] val) throws PortableException { - writeFieldId(fieldName, ENUM_ARR); - writeEnumArrayField(val); - } - - /** {@inheritDoc} */ - @Override public <T extends Enum<?>> void writeEnumArray(T[] val) throws PortableException { - doWriteEnumArray(val); - } - - /** {@inheritDoc} */ - @Override public PortableRawWriter rawWriter() { - if (allowFields) { - wCtx.out.writeInt(start + RAW_DATA_OFF_POS, wCtx.out.position() - start); - - allowFields = false; - } - - return this; - } - - /** {@inheritDoc} */ - @Override public GridPortableOutputStream out() { - return wCtx.out; - } - - /** {@inheritDoc} */ - @Override public void writeBytes(String s) throws IOException { - int len = s.length(); - - writeInt(len); - - for (int i = 0; i < len; i++) - writeByte(s.charAt(i)); - } - - /** {@inheritDoc} */ - @Override public void writeChars(String s) throws IOException { - int len = s.length(); - - writeInt(len); - - for (int i = 0; i < len; i++) - writeChar(s.charAt(i)); - } - - /** {@inheritDoc} */ - @Override public void writeUTF(String s) throws IOException { - writeString(s); - } - - /** {@inheritDoc} */ - @Override public void writeByte(int v) throws IOException { - doWriteByte((byte)v); - } - - /** {@inheritDoc} */ - @Override public void writeShort(int v) throws IOException { - doWriteShort((short)v); - } - - /** {@inheritDoc} */ - @Override public void writeChar(int v) throws IOException { - doWriteChar((char)v); - } - - /** {@inheritDoc} */ - @Override public void write(int b) throws IOException { - doWriteByte((byte)b); - } - - /** {@inheritDoc} */ - @Override public void flush() throws IOException { - // No-op. - } - - /** - * Reserve a room for an integer. - * - * @return Position in the stream where value is to be written. - */ - public int reserveInt() { - return reserve(LEN_INT); - } - - /** - * Write int value at the specific position. - * - * @param pos Position. - * @param val Value. - * @throws PortableException If failed. - */ - public void writeInt(int pos, int val) throws PortableException { - wCtx.out.writeInt(pos, val); - } - - /** - * @param fieldName Field name. - * @throws PortableException If fields are not allowed. - */ - private void writeFieldId(String fieldName, byte fieldType) throws PortableException { - A.notNull(fieldName, "fieldName"); - - if (!allowFields) - throw new PortableException("Individual field can't be written after raw writer is acquired " + - "via rawWriter() method. Consider fixing serialization logic for class: " + cls.getName()); - - int id = ctx.fieldId(typeId, fieldName); - - if (metaEnabled) - metaHashSum = 31 * metaHashSum + (id + fieldType); - - doWriteInt(id); - } - - /** - * Create new writer with same context. - * @param typeId type - * @return New writer. - */ - GridPortableWriterExImpl newWriter(int typeId) { - GridPortableWriterExImpl res = new GridPortableWriterExImpl(ctx, wCtx); - - res.typeId = typeId; - - return res; - } - - /** - * @return Portable context. - */ - GridPortableContext context() { - return ctx; - } - - /** */ - private static class WriterContext { - /** */ - private Map<Object, Integer> handles = new IdentityHashMap<>(); - - /** Output stream. */ - private GridPortableOutputStream out; - - /** - * Constructor. - * - * @param out Output stream. - * @param handles Handles. - */ - private WriterContext(GridPortableOutputStream out, Map<Object, Integer> handles) { - this.out = out; - this.handles = handles == null ? new IdentityHashMap<Object, Integer>() : handles; - } - - /** - * @param obj Object. - * @return Handle. - */ - private int handle(Object obj) { - assert obj != null; - - Integer h = handles.get(obj); - - if (h != null) - return out.position() - h; - else { - handles.put(obj, out.position()); - - return -1; - } - } - - /** - * - */ - private void resetHandles() { - handles = new IdentityHashMap<>(); - } - } -}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java new file mode 100644 index 0000000..83b3050 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableAbstractLazyValue.java @@ -0,0 +1,57 @@ +/* + * 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.portable; + +/** + * + */ +abstract class PortableAbstractLazyValue implements PortableLazyValue { + /** */ + protected Object val; + + /** */ + protected final PortableBuilderReader reader; + + /** */ + protected final int valOff; + + /** + * @param reader Reader. + * @param valOff Value. + */ + protected PortableAbstractLazyValue(PortableBuilderReader reader, int valOff) { + this.reader = reader; + this.valOff = valOff; + } + + /** + * @return Value. + */ + protected abstract Object init(); + + /** {@inheritDoc} */ + @Override public Object value() { + if (val == null) { + val = init(); + + assert val != null; + } + + return val; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java new file mode 100644 index 0000000..eec68a5 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderEnum.java @@ -0,0 +1,114 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.portable.*; + +/** + * + */ +public class PortableBuilderEnum implements PortableBuilderSerializationAware { + /** */ + private final int ordinal; + + /** */ + private final int typeId; + + /** */ + private final String clsName; + + /** + * @param typeId Type ID. + * @param anEnum Enum instance. + */ + public PortableBuilderEnum(int typeId, Enum anEnum) { + ordinal = anEnum.ordinal(); + this.typeId = typeId; + clsName = null; + } + + /** + * @param reader PortableBuilderReader. + */ + public PortableBuilderEnum(PortableBuilderReader reader) { + int typeId = reader.readInt(); + + if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) { + clsName = reader.readString(); + + Class cls; + + try { + // TODO: GG-10396 - Is class loader needed here? + cls = U.forName(reader.readString(), null); + } + catch (ClassNotFoundException e) { + throw new PortableInvalidClassException("Failed to load the class: " + clsName, e); + } + + this.typeId = reader.portableContext().descriptorForClass(cls).typeId(); + } + else { + this.typeId = typeId; + this.clsName = null; + } + + ordinal = reader.readInt(); + } + + /** + * @return Ordinal. + */ + public int getOrdinal() { + return ordinal; + } + + /** {@inheritDoc} */ + @Override public void writeTo(PortableWriterExImpl writer, PortableBuilderSerializer ctx) { + writer.writeByte(GridPortableMarshaller.ENUM); + + if (typeId == GridPortableMarshaller.UNREGISTERED_TYPE_ID) { + writer.writeInt(GridPortableMarshaller.UNREGISTERED_TYPE_ID); + writer.writeString(clsName); + } + else + writer.writeInt(typeId); + + writer.writeInt(ordinal); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) + return false; + + PortableBuilderEnum that = (PortableBuilderEnum)o; + + return ordinal == that.ordinal && typeId == that.typeId; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int result = ordinal; + + result = 31 * result + typeId; + + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4662feca/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java new file mode 100644 index 0000000..d471748 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableBuilderImpl.java @@ -0,0 +1,519 @@ +/* + * 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.portable; + +import org.apache.ignite.internal.processors.cache.portable.*; +import org.apache.ignite.internal.util.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.portable.*; + +import org.jetbrains.annotations.*; + +import java.util.*; + +import static org.apache.ignite.internal.portable.GridPortableMarshaller.*; + +/** + * + */ +public class PortableBuilderImpl implements PortableBuilder { + /** */ + private static final Object REMOVED_FIELD_MARKER = new Object(); + + /** */ + private final PortableContext ctx; + + /** */ + private final int typeId; + + /** May be null. */ + private String typeName; + + /** May be null. */ + private String clsNameToWrite; + + /** */ + private boolean registeredType = true; + + /** */ + private Map<String, Object> assignedVals; + + /** */ + private Map<Integer, Object> readCache; + + /** Position of object in source array, or -1 if object is not created from PortableObject. */ + private final int start; + + /** Total header length */ + private final int hdrLen; + + /** + * Context of PortableObject reading process. Or {@code null} if object is not created from PortableObject. + */ + private final PortableBuilderReader reader; + + /** */ + private int hashCode; + + /** + * @param clsName Class name. + * @param ctx Portable context. + */ + public PortableBuilderImpl(PortableContext ctx, String clsName) { + this(ctx, ctx.typeId(clsName), PortableContext.typeName(clsName)); + } + + /** + * @param typeId Type ID. + * @param ctx Portable context. + */ + public PortableBuilderImpl(PortableContext ctx, int typeId) { + this(ctx, typeId, null); + } + + /** + * @param typeName Type name. + * @param ctx Context. + * @param typeId Type id. + */ + public PortableBuilderImpl(PortableContext ctx, int typeId, String typeName) { + this.typeId = typeId; + this.typeName = typeName; + this.ctx = ctx; + + start = -1; + reader = null; + hdrLen = DFLT_HDR_LEN; + + readCache = Collections.emptyMap(); + } + + /** + * @param obj Object to wrap. + */ + public PortableBuilderImpl(PortableObjectImpl obj) { + this(new PortableBuilderReader(obj), obj.start()); + + reader.registerObject(this); + } + + /** + * @param reader ctx + * @param start Start. + */ + PortableBuilderImpl(PortableBuilderReader reader, int start) { + this.reader = reader; + this.start = start; + + int typeId = reader.readIntAbsolute(start + TYPE_ID_POS); + ctx = reader.portableContext(); + hashCode = reader.readIntAbsolute(start + HASH_CODE_POS); + + if (typeId == UNREGISTERED_TYPE_ID) { + int mark = reader.position(); + + reader.position(start + CLS_NAME_POS); + + clsNameToWrite = reader.readString(); + + Class cls; + + try { + // TODO: GG-10396 - Is class loader needed here? + cls = U.forName(clsNameToWrite, null); + } + catch (ClassNotFoundException e) { + throw new PortableInvalidClassException("Failed to load the class: " + clsNameToWrite, e); + } + + this.typeId = ctx.descriptorForClass(cls).typeId(); + + registeredType = false; + + hdrLen = reader.position() - mark; + + reader.position(mark); + } + else { + this.typeId = typeId; + hdrLen = DFLT_HDR_LEN; + } + } + + /** {@inheritDoc} */ + @Override public PortableObject build() { + try (PortableWriterExImpl writer = new PortableWriterExImpl(ctx, 0, typeId, false)) { + + PortableBuilderSerializer serializationCtx = new PortableBuilderSerializer(); + + serializationCtx.registerObjectWriting(this, 0); + + serializeTo(writer, serializationCtx); + + byte[] arr = writer.array(); + + return new PortableObjectImpl(ctx, arr, 0); + } + } + + /** + * @param writer Writer. + * @param serializer Serializer. + */ + void serializeTo(PortableWriterExImpl writer, PortableBuilderSerializer serializer) { + writer.doWriteByte(GridPortableMarshaller.OBJ); + writer.doWriteBoolean(true); + writer.doWriteInt(registeredType ? typeId : UNREGISTERED_TYPE_ID); + writer.doWriteInt(hashCode); + + // Length and raw offset. + writer.reserve(8); + + if (!registeredType) + writer.writeString(clsNameToWrite); + + + Set<Integer> remainsFlds = null; + + if (reader != null) { + Map<Integer, Object> assignedFldsById; + + if (assignedVals != null) { + assignedFldsById = U.newHashMap(assignedVals.size()); + + for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { + int fldId = ctx.fieldId(typeId, entry.getKey()); + + assignedFldsById.put(fldId, entry.getValue()); + } + + remainsFlds = assignedFldsById.keySet(); + } + else + assignedFldsById = Collections.emptyMap(); + + int rawOff = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS); + + reader.position(start + hdrLen); + + int cpStart = -1; + + while (reader.position() < rawOff) { + int fldId = reader.readInt(); + + int len = reader.readInt(); + + if (assignedFldsById.containsKey(fldId)) { + if (cpStart >= 0) { + writer.write(reader.array(), cpStart, reader.position() - 4 - 4 - cpStart); + + cpStart = -1; + } + + Object assignedVal = assignedFldsById.remove(fldId); + + reader.skip(len); + + if (assignedVal != REMOVED_FIELD_MARKER) { + writer.writeInt(fldId); + + int lenPos = writer.reserveAndMark(4); + + serializer.writeValue(writer, assignedVal); + + writer.writeDelta(lenPos); + } + } + else { + if (len != 0 && PortableUtils.isPlainType(reader.readByte(0))) { + if (cpStart < 0) + cpStart = reader.position() - 4 - 4; + + reader.skip(len); + } + else { + if (cpStart >= 0) { + writer.write(reader.array(), cpStart, reader.position() - 4 - cpStart); + + cpStart = -1; + } + else + writer.writeInt(fldId); + + Object val; + + if (len == 0) + val = null; + else if (readCache == null) { + int savedPos = reader.position(); + + val = reader.parseValue(); + + assert reader.position() == savedPos + len; + } + else { + val = readCache.get(fldId); + + reader.skip(len); + } + + int lenPos = writer.reserveAndMark(4); + + serializer.writeValue(writer, val); + + writer.writeDelta(lenPos); + } + } + } + + if (cpStart >= 0) + writer.write(reader.array(), cpStart, reader.position() - cpStart); + } + + if (assignedVals != null && (remainsFlds == null || !remainsFlds.isEmpty())) { + boolean metadataEnabled = ctx.isMetaDataEnabled(typeId); + + PortableMetadata metadata = null; + + if (metadataEnabled) + metadata = ctx.metaData(typeId); + + Map<String, String> newFldsMetadata = null; + + for (Map.Entry<String, Object> entry : assignedVals.entrySet()) { + Object val = entry.getValue(); + + if (val == REMOVED_FIELD_MARKER) + continue; + + String name = entry.getKey(); + + int fldId = ctx.fieldId(typeId, name); + + if (remainsFlds != null && !remainsFlds.contains(fldId)) + continue; + + writer.writeInt(fldId); + + int lenPos = writer.reserveAndMark(4); + + serializer.writeValue(writer, val); + + writer.writeDelta(lenPos); + + if (metadataEnabled) { + String oldFldTypeName = metadata == null ? null : metadata.fieldTypeName(name); + + String newFldTypeName; + + if (val instanceof PortableValueWithType) + newFldTypeName = ((PortableValueWithType)val).typeName(); + else { + byte type = PortableUtils.typeByClass(val.getClass()); + + newFldTypeName = CacheObjectPortableProcessorImpl.fieldTypeName(type); + } + + if (oldFldTypeName == null) { + // It's a new field, we have to add it to metadata. + + if (newFldsMetadata == null) + newFldsMetadata = new HashMap<>(); + + newFldsMetadata.put(name, newFldTypeName); + } + else { + if (!"Object".equals(oldFldTypeName) && !oldFldTypeName.equals(newFldTypeName)) { + throw new PortableException( + "Wrong value has been set [" + + "typeName=" + (typeName == null ? metadata.typeName() : typeName) + + ", fieldName=" + name + + ", fieldType=" + oldFldTypeName + + ", assignedValueType=" + newFldTypeName + + ", assignedValue=" + (((PortableValueWithType)val).value()) + ']' + ); + } + } + } + } + + if (newFldsMetadata != null) { + String typeName = this.typeName; + + if (typeName == null) + typeName = metadata.typeName(); + + ctx.updateMetaData(typeId, typeName, newFldsMetadata); + } + } + + writer.writeRawOffsetIfNeeded(); + + if (reader != null) { + int rawOff = reader.readIntAbsolute(start + RAW_DATA_OFF_POS); + int len = reader.readIntAbsolute(start + TOTAL_LEN_POS); + + if (rawOff < len) + writer.write(reader.array(), rawOff, len - rawOff); + } + + writer.writeLength(); + } + + /** {@inheritDoc} */ + @Override public PortableBuilderImpl hashCode(int hashCode) { + this.hashCode = hashCode; + + return this; + } + + /** + * + */ + private void ensureReadCacheInit() { + if (readCache == null) { + Map<Integer, Object> readCache = new HashMap<>(); + + int pos = start + hdrLen; + int end = start + reader.readIntAbsolute(start + RAW_DATA_OFF_POS); + + while (pos < end) { + int fieldId = reader.readIntAbsolute(pos); + + pos += 4; + + int len = reader.readIntAbsolute(pos); + + pos += 4; + + Object val = reader.getValueQuickly(pos, len); + + readCache.put(fieldId, val); + + pos += len; + } + + this.readCache = readCache; + } + } + + /** {@inheritDoc} */ + @Override public <F> F getField(String name) { + Object val; + + if (assignedVals != null && assignedVals.containsKey(name)) { + val = assignedVals.get(name); + + if (val == REMOVED_FIELD_MARKER) + return null; + } + else { + ensureReadCacheInit(); + + int fldId = ctx.fieldId(typeId, name); + + val = readCache.get(fldId); + } + + return (F)PortableUtils.unwrapLazy(val); + } + + /** {@inheritDoc} */ + @Override public PortableBuilder setField(String name, Object val) { + GridArgumentCheck.notNull(val, "val"); + + if (assignedVals == null) + assignedVals = new LinkedHashMap<>(); + + Object oldVal = assignedVals.put(name, val); + + if (oldVal instanceof PortableValueWithType) { + ((PortableValueWithType)oldVal).value(val); + + assignedVals.put(name, oldVal); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public <T> PortableBuilder setField(String name, @Nullable T val, Class<? super T> type) { + if (assignedVals == null) + assignedVals = new LinkedHashMap<>(); + + //int fldId = ctx.fieldId(typeId, fldName); + + assignedVals.put(name, new PortableValueWithType(PortableUtils.typeByClass(type), val)); + + return this; + } + + /** {@inheritDoc} */ + @Override public PortableBuilder setField(String name, @Nullable PortableBuilder builder) { + if (builder == null) + return setField(name, null, Object.class); + else + return setField(name, (Object)builder); + } + + /** + * Removes field from portable object. + * + * @param name Field name. + * @return {@code this} instance for chaining. + */ + @Override public PortableBuilderImpl removeField(String name) { + if (assignedVals == null) + assignedVals = new LinkedHashMap<>(); + + assignedVals.put(name, REMOVED_FIELD_MARKER); + + return this; + } + + /** + * Creates builder initialized by specified portable object. + * + * @param obj Portable object to initialize builder. + * @return New builder. + */ + public static PortableBuilderImpl wrap(PortableObject obj) { + PortableObjectImpl heapObj; + + if (obj instanceof PortableObjectOffheapImpl) + heapObj = (PortableObjectImpl)((PortableObjectOffheapImpl)obj).heapCopy(); + else + heapObj = (PortableObjectImpl)obj; + + return new PortableBuilderImpl(heapObj); + } + + /** + * @return Object start position in source array. + */ + int start() { + return start; + } + + /** + * @return Object type id. + */ + int typeId() { + return typeId; + } +}