blob: 743958932f21b3dc34a5317d2182a31445933111 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.binary;
import org.apache.ignite.IgniteIllegalStateException;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.IgnitionEx;
import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
import org.apache.ignite.internal.binary.streams.BinaryInputStream;
import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.jetbrains.annotations.Nullable;
/**
* Binary objects marshaller.
*/
public class GridBinaryMarshaller {
/** */
public static final ThreadLocal<Boolean> KEEP_BINARIES = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
return true;
}
};
/** Binary context in TLS store. */
private static final ThreadLocal<BinaryContext> BINARY_CTX = new ThreadLocal<>();
/** */
public static final byte OPTM_MARSH = -2;
/** */
public static final byte BYTE = 1;
/** */
public static final byte SHORT = 2;
/** */
public static final byte INT = 3;
/** */
public static final byte LONG = 4;
/** */
public static final byte FLOAT = 5;
/** */
public static final byte DOUBLE = 6;
/** */
public static final byte CHAR = 7;
/** */
public static final byte BOOLEAN = 8;
/** */
public static final byte DECIMAL = 30;
/** */
public static final byte STRING = 9;
/** */
public static final byte UUID = 10;
/** */
public static final byte DATE = 11;
/** */
public static final byte BYTE_ARR = 12;
/** */
public static final byte SHORT_ARR = 13;
/** */
public static final byte INT_ARR = 14;
/** */
public static final byte LONG_ARR = 15;
/** */
public static final byte FLOAT_ARR = 16;
/** */
public static final byte DOUBLE_ARR = 17;
/** */
public static final byte CHAR_ARR = 18;
/** */
public static final byte BOOLEAN_ARR = 19;
/** */
public static final byte DECIMAL_ARR = 31;
/** */
public static final byte STRING_ARR = 20;
/** */
public static final byte UUID_ARR = 21;
/** */
public static final byte DATE_ARR = 22;
/** */
public static final byte OBJ_ARR = 23;
/** */
public static final byte COL = 24;
/** */
public static final byte MAP = 25;
/** */
public static final byte BINARY_OBJ = 27;
/** */
public static final byte ENUM = 28;
/** */
public static final byte ENUM_ARR = 29;
/** */
public static final byte CLASS = 32;
/** Timestamp. */
public static final byte TIMESTAMP = 33;
/** Timestamp array. */
public static final byte TIMESTAMP_ARR = 34;
/** Proxy. */
public static final byte PROXY = 35;
/** Time. */
public static final byte TIME = 36;
/** Time array. */
public static final byte TIME_ARR = 37;
/** Binary enum */
public static final byte BINARY_ENUM = 38;
/** */
public static final byte NULL = (byte)101;
/** */
public static final byte HANDLE = (byte)102;
/** */
public static final byte OBJ = (byte)103;
/** */
public static final byte USER_SET = -1;
/** */
public static final byte USER_COL = 0;
/** */
public static final byte ARR_LIST = 1;
/** */
public static final byte LINKED_LIST = 2;
/** */
public static final byte HASH_SET = 3;
/** */
public static final byte LINKED_HASH_SET = 4;
/** */
public static final byte SINGLETON_LIST = 5;
/** */
public static final byte HASH_MAP = 1;
/** */
public static final byte LINKED_HASH_MAP = 2;
/** */
public static final byte PLATFORM_JAVA_OBJECT_FACTORY_PROXY = 99;
/** */
public static final int OBJECT = -1;
/** */
public static final int UNREGISTERED_TYPE_ID = 0;
/** Protocol version. */
public static final byte PROTO_VER = 1;
/** Protocol version position. */
public static final int PROTO_VER_POS = 1;
/** Flags position in header. */
public static final int FLAGS_POS = 2;
/** */
public static final int TYPE_ID_POS = 4;
/** */
public static final int HASH_CODE_POS = 8;
/** */
public static final int TOTAL_LEN_POS = 12;
/** */
public static final int SCHEMA_ID_POS = 16;
/** Schema or raw offset position. */
public static final int SCHEMA_OR_RAW_OFF_POS = 20;
/** */
public static final byte DFLT_HDR_LEN = 24;
/** */
private final BinaryContext ctx;
/**
* @param ctx Context.
*/
public GridBinaryMarshaller(BinaryContext ctx) {
this.ctx = ctx;
}
/**
* @param obj Object to marshal.
* @param failIfUnregistered Throw exception if class isn't registered.
* @return Byte array.
* @throws org.apache.ignite.binary.BinaryObjectException In case of error.
*/
public byte[] marshal(@Nullable Object obj, boolean failIfUnregistered) throws BinaryObjectException {
if (obj == null)
return new byte[] { NULL };
try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx)) {
writer.failIfUnregistered(failIfUnregistered);
writer.marshal(obj);
return writer.array();
}
}
/**
* @param bytes Bytes array.
* @return Binary object.
* @throws org.apache.ignite.binary.BinaryObjectException In case of error.
*/
@SuppressWarnings("unchecked")
@Nullable public <T> T unmarshal(byte[] bytes, @Nullable ClassLoader clsLdr) throws BinaryObjectException {
assert bytes != null;
BinaryContext oldCtx = pushContext(ctx);
try {
return (T) BinaryUtils.unmarshal(BinaryHeapInputStream.create(bytes, 0), ctx, clsLdr);
}
finally {
popContext(oldCtx);
}
}
/**
* @param in Input stream.
* @return Binary object.
* @throws org.apache.ignite.binary.BinaryObjectException In case of error.
*/
@SuppressWarnings("unchecked")
@Nullable public <T> T unmarshal(BinaryInputStream in) throws BinaryObjectException {
BinaryContext oldCtx = pushContext(ctx);
try {
return (T)BinaryUtils.unmarshal(in, ctx, null);
}
finally {
popContext(oldCtx);
}
}
/**
* @param arr Byte array.
* @param ldr Class loader.
* @return Deserialized object.
* @throws org.apache.ignite.binary.BinaryObjectException In case of error.
*/
@SuppressWarnings("unchecked")
@Nullable public <T> T deserialize(byte[] arr, @Nullable ClassLoader ldr) throws BinaryObjectException {
assert arr != null;
assert arr.length > 0;
if (arr[0] == NULL)
return null;
BinaryContext oldCtx = pushContext(ctx);
try {
return (T)new BinaryReaderExImpl(ctx, BinaryHeapInputStream.create(arr, 0), ldr, true).deserialize();
}
finally {
popContext(oldCtx);
}
}
/**
* Push binary context and return the old one.
*
* @return Old binary context.
*/
public BinaryContext pushContext() {
return pushContext(ctx);
}
/**
* Push binary context and return the old one.
*
* @param ctx Binary context.
* @return Old binary context.
*/
@Nullable private static BinaryContext pushContext(BinaryContext ctx) {
BinaryContext old = BINARY_CTX.get();
BINARY_CTX.set(ctx);
return old;
}
/**
* Pop binary context and restore the old one.
*
* @param oldCtx Old binary context.
*/
public static void popContext(@Nullable BinaryContext oldCtx) {
BINARY_CTX.set(oldCtx);
}
/**
* Creates a reader.
*
* @param stream Stream.
* @return Reader.
*/
public BinaryReaderExImpl reader(BinaryInputStream stream) {
assert stream != null;
return new BinaryReaderExImpl(ctx, stream, null, true);
}
/**
* Whether object must be deserialized anyway. I.e. it cannot be converted to BinaryObject.
*
* @param obj Object.
* @return {@code True} if object will be deserialized on unmarshal.
*/
public boolean mustDeserialize(Object obj) {
return obj != null && ctx.mustDeserialize(obj.getClass());
}
/**
* Gets writer for the given output stream.
*
* @param out Output stream.
* @return Writer.
*/
public BinaryWriterExImpl writer(BinaryOutputStream out) {
return new BinaryWriterExImpl(ctx, out, BinaryThreadLocalContext.get().schemaHolder(), null);
}
/**
* @return Context.
*/
public BinaryContext context() {
return ctx;
}
/**
* @return Thread-bound context.
*/
public static BinaryContext threadLocalContext() {
BinaryContext ctx = GridBinaryMarshaller.BINARY_CTX.get();
if (ctx == null) {
IgniteKernal ignite = IgnitionEx.localIgnite();
IgniteCacheObjectProcessor proc = ignite.context().cacheObjects();
if (proc instanceof CacheObjectBinaryProcessorImpl)
return ((CacheObjectBinaryProcessorImpl)proc).binaryContext();
else
throw new IgniteIllegalStateException("Ignite instance must be started with " +
BinaryMarshaller.class.getName() + " [name=" + ignite.name() + ']');
}
return ctx;
}
}