Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.internal.serialization.impl;
import com.hazelcast.core.ManagedContext;
import com.hazelcast.internal.serialization.InternalSerializationService;
import com.hazelcast.internal.serialization.PortableContext;
import com.hazelcast.nio.Bits;
import com.hazelcast.nio.BufferObjectDataInput;
import com.hazelcast.nio.serialization.ClassDefinition;
import com.hazelcast.nio.serialization.ClassDefinitionBuilder;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.nio.serialization.FieldDefinition;
import com.hazelcast.nio.serialization.FieldType;
import com.hazelcast.nio.serialization.HazelcastSerializationException;
import com.hazelcast.nio.serialization.Portable;
import com.hazelcast.util.ConcurrencyUtil;
import com.hazelcast.util.ConstructorFunction;
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;
import static com.hazelcast.nio.Bits.combineToLong;
import static com.hazelcast.query.impl.getters.ExtractorHelper.extractAttributeNameNameWithoutArguments;
final class PortableContextImpl implements PortableContext {
private static final Pattern NESTED_FIELD_PATTERN = Pattern.compile("\\.");
private final int version;
private final ConcurrentHashMap classDefContextMap =
new ConcurrentHashMap();
private final InternalSerializationService serializationService;
private final ConstructorFunction constructorFunction =
new ConstructorFunction() {
public ClassDefinitionContext createNew(Integer arg) {
return new ClassDefinitionContext(arg);
}
};
PortableContextImpl(InternalSerializationService serializationService, int version) {
this.serializationService = serializationService;
this.version = version;
}
@Override
public int getClassVersion(int factoryId, int classId) {
return getClassDefContext(factoryId).getClassVersion(classId);
}
@Override
public void setClassVersion(int factoryId, int classId, int version) {
getClassDefContext(factoryId).setClassVersion(classId, version);
}
@Override
public ClassDefinition lookupClassDefinition(int factoryId, int classId, int version) {
return getClassDefContext(factoryId).lookup(classId, version);
}
@Override
public ClassDefinition lookupClassDefinition(Data data) throws IOException {
if (!data.isPortable()) {
throw new IllegalArgumentException("Data is not Portable!");
}
BufferObjectDataInput in = serializationService.createObjectDataInput(data);
int factoryId = in.readInt();
int classId = in.readInt();
int version = in.readInt();
ClassDefinition classDefinition = lookupClassDefinition(factoryId, classId, version);
if (classDefinition == null) {
classDefinition = readClassDefinition(in, factoryId, classId, version);
}
return classDefinition;
}
ClassDefinition readClassDefinition(BufferObjectDataInput in, int factoryId, int classId, int version)
throws IOException {
boolean register = true;
ClassDefinitionBuilder builder = new ClassDefinitionBuilder(factoryId, classId, version);
// final position after portable is read
in.readInt();
// field count
int fieldCount = in.readInt();
int offset = in.position();
for (int i = 0; i < fieldCount; i++) {
int pos = in.readInt(offset + i * Bits.INT_SIZE_IN_BYTES);
in.position(pos);
short len = in.readShort();
char[] chars = new char[len];
for (int k = 0; k < len; k++) {
chars[k] = (char) in.readUnsignedByte();
}
FieldType type = FieldType.get(in.readByte());
String name = new String(chars);
int fieldFactoryId = 0;
int fieldClassId = 0;
if (type == FieldType.PORTABLE) {
// is null
if (in.readBoolean()) {
register = false;
}
fieldFactoryId = in.readInt();
fieldClassId = in.readInt();
// TODO: what there's a null inner Portable field
if (register) {
int fieldVersion = in.readInt();
readClassDefinition(in, fieldFactoryId, fieldClassId, fieldVersion);
}
} else if (type == FieldType.PORTABLE_ARRAY) {
int k = in.readInt();
fieldFactoryId = in.readInt();
fieldClassId = in.readInt();
// TODO: what there's a null inner Portable field
if (k > 0) {
int p = in.readInt();
in.position(p);
int fieldVersion = in.readInt();
readClassDefinition(in, fieldFactoryId, fieldClassId, fieldVersion);
} else {
register = false;
}
}
builder.addField(new FieldDefinitionImpl(i, name, type, fieldFactoryId, fieldClassId));
}
ClassDefinition classDefinition = builder.build();
if (register) {
classDefinition = registerClassDefinition(classDefinition);
}
return classDefinition;
}
@Override
public ClassDefinition registerClassDefinition(final ClassDefinition cd) {
return getClassDefContext(cd.getFactoryId()).register(cd);
}
@Override
public ClassDefinition lookupOrRegisterClassDefinition(Portable p) throws IOException {
int portableVersion = SerializationUtil.getPortableVersion(p, version);
ClassDefinition cd = lookupClassDefinition(p.getFactoryId(), p.getClassId(), portableVersion);
if (cd == null) {
ClassDefinitionWriter writer = new ClassDefinitionWriter(this, p.getFactoryId(),
p.getClassId(), portableVersion);
p.writePortable(writer);
cd = writer.registerAndGet();
}
return cd;
}
@Override
// TODO cache the result
public FieldDefinition getFieldDefinition(ClassDefinition classDef, String name) {
FieldDefinition fd = classDef.getField(name);
if (fd == null) {
if (name.contains(".")) {
String[] fieldNames = NESTED_FIELD_PATTERN.split(name);
if (fieldNames.length <= 1) {
return fd;
}
ClassDefinition currentClassDef = classDef;
for (int i = 0; i < fieldNames.length; i++) {
fd = currentClassDef.getField(fieldNames[i]);
if (fd == null) {
fd = currentClassDef.getField(extractAttributeNameNameWithoutArguments(fieldNames[i]));
}
// This is not enough to fully implement issue: https://github.com/hazelcast/hazelcast/issues/3927
if (i == fieldNames.length - 1) {
break;
}
if (fd == null) {
throw new IllegalArgumentException("Unknown field: " + name);
}
currentClassDef = lookupClassDefinition(fd.getFactoryId(), fd.getClassId(),
currentClassDef.getVersion());
if (currentClassDef == null) {
throw new IllegalArgumentException("Not a registered Portable field: " + fd);
}
}
} else {
fd = classDef.getField(extractAttributeNameNameWithoutArguments(name));
}
}
return fd;
}
private ClassDefinitionContext getClassDefContext(int factoryId) {
return ConcurrencyUtil.getOrPutIfAbsent(classDefContextMap, factoryId, constructorFunction);
}
@Override
public int getVersion() {
return version;
}
@Override
public ManagedContext getManagedContext() {
return serializationService.getManagedContext();
}
@Override
public ByteOrder getByteOrder() {
return serializationService.getByteOrder();
}
private final class ClassDefinitionContext {
final int factoryId;
final ConcurrentMap versionedDefinitions = new ConcurrentHashMap();
final ConcurrentMap currentClassVersions = new ConcurrentHashMap();
private ClassDefinitionContext(int factoryId) {
this.factoryId = factoryId;
}
int getClassVersion(int classId) {
Integer version = currentClassVersions.get(classId);
return version != null ? version : -1;
}
void setClassVersion(int classId, int version) {
Integer current = currentClassVersions.putIfAbsent(classId, version);
if (current != null && current != version) {
throw new IllegalArgumentException("Class-id: " + classId + " is already registered!");
}
}
ClassDefinition lookup(int classId, int version) {
long versionedClassId = combineToLong(classId, version);
return versionedDefinitions.get(versionedClassId);
}
ClassDefinition register(ClassDefinition cd) {
if (cd == null) {
return null;
}
if (cd.getFactoryId() != factoryId) {
throw new HazelcastSerializationException("Invalid factory-id! " + factoryId + " -> " + cd);
}
if (cd instanceof ClassDefinitionImpl) {
final ClassDefinitionImpl cdImpl = (ClassDefinitionImpl) cd;
cdImpl.setVersionIfNotSet(getVersion());
}
final long versionedClassId = combineToLong(cd.getClassId(), cd.getVersion());
final ClassDefinition currentCd = versionedDefinitions.putIfAbsent(versionedClassId, cd);
if (currentCd == null) {
return cd;
}
if (currentCd instanceof ClassDefinitionImpl) {
if (!currentCd.equals(cd)) {
throw new HazelcastSerializationException(
"Incompatible class-definitions with same class-id: " + cd + " VS " + currentCd);
}
return currentCd;
}
versionedDefinitions.put(versionedClassId, cd);
return cd;
}
}
}