Package com.hazelcast.nio.serialization

Source Code of com.hazelcast.nio.serialization.SerializationContextImpl$PortableContext

/*
* Copyright (c) 2008-2013, 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.nio.serialization;

import com.hazelcast.core.ManagedContext;
import com.hazelcast.nio.BufferObjectDataOutput;
import com.hazelcast.util.ConcurrencyUtil;
import com.hazelcast.util.ConstructorFunction;

import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

/**
* @author mdogan 7/29/13
*/
final class SerializationContextImpl implements SerializationContext {

    final int version;
    final ConcurrentHashMap<Integer, PortableContext> portableContextMap = new ConcurrentHashMap<Integer, PortableContext>();
    final SerializationServiceImpl serializationService;
    final ConstructorFunction<Integer, PortableContext> constructorFunction = new ConstructorFunction<Integer, PortableContext>() {
        public PortableContext createNew(Integer arg) {
            return new PortableContext();
        }
    };

    SerializationContextImpl(SerializationServiceImpl serializationService, Collection<Integer> portableFactories, int version) {
        this.serializationService = serializationService;
        this.version = version;

        for (int factoryId : portableFactories) {
            portableContextMap.put(factoryId, new PortableContext()) ;
        }
    }

    public ClassDefinition lookup(int factoryId, int classId) {
        return getPortableContext(factoryId).lookup(classId, version);
    }

    public ClassDefinition lookup(int factoryId, int classId, int version) {
        return getPortableContext(factoryId).lookup(classId, version);
    }

    public ClassDefinition createClassDefinition(int factoryId, final byte[] compressedBinary) throws IOException {
        return getPortableContext(factoryId).createClassDefinition(compressedBinary);
    }

    public ClassDefinition registerClassDefinition(final ClassDefinition cd) {
        return getPortableContext(cd.getFactoryId()).registerClassDefinition(cd);
    }

    public ClassDefinition lookupOrRegisterClassDefinition(Portable p) throws IOException {
        ClassDefinition cd = lookup(p.getFactoryId(), p.getClassId());
        if (cd == null) {
            ClassDefinitionWriter classDefinitionWriter = new ClassDefinitionWriter(this, p.getFactoryId(), p.getClassId());
            p.writePortable(classDefinitionWriter);
            cd = classDefinitionWriter.registerAndGet();
        }
        return cd;
    }

    private void registerNestedDefinitions(ClassDefinitionImpl cd) {
        Collection<ClassDefinition> nestedDefinitions = cd.getNestedClassDefinitions();
        for (ClassDefinition classDefinition : nestedDefinitions) {
            final ClassDefinitionImpl nestedCD = (ClassDefinitionImpl) classDefinition;
            registerClassDefinition(nestedCD);
            registerNestedDefinitions(nestedCD);
        }
    }

    private PortableContext getPortableContext(int factoryId) {
        return ConcurrencyUtil.getOrPutIfAbsent(portableContextMap, factoryId, constructorFunction);
    }

    public int getVersion() {
        return version;
    }

    public ManagedContext getManagedContext() {
        return serializationService.getManagedContext();
    }

    private class PortableContext {

        final ConcurrentMap<Long, ClassDefinitionImpl> versionedDefinitions = new ConcurrentHashMap<Long, ClassDefinitionImpl>();

        ClassDefinition lookup(int classId, int version) {
            return versionedDefinitions.get(combineToLong(classId, version));
        }

        ClassDefinition createClassDefinition(byte[] compressedBinary) throws IOException {
            if (compressedBinary == null || compressedBinary.length == 0) {
                throw new IOException("Illegal class-definition binary! ");
            }
            final BufferObjectDataOutput out = serializationService.pop();
            final byte[] binary;
            try {
                decompress(compressedBinary, out);
                binary = out.toByteArray();
            } finally {
                serializationService.push(out);
            }
            final ClassDefinitionImpl cd = new ClassDefinitionImpl();
            cd.readData(serializationService.createObjectDataInput(binary));
            cd.setBinary(compressedBinary);
            return registerClassDefinition(cd);
        }

        ClassDefinition registerClassDefinition(ClassDefinition cd) {
            if (cd == null) return null;
            final ClassDefinitionImpl cdImpl = (ClassDefinitionImpl) cd;
            if (cdImpl.getVersion() < 0) {
                cdImpl.version = getVersion();
            }
            if (cdImpl.getBinary() == null) {
                final BufferObjectDataOutput out = serializationService.pop();
                try {
                    cdImpl.writeData(out);
                    final byte[] binary = out.toByteArray();
                    out.clear();
                    compress(binary, out);
                    cdImpl.setBinary(out.toByteArray());
                } catch (IOException e) {
                    throw new HazelcastSerializationException(e);
                } finally {
                    serializationService.push(out);
                }
            }
            final long versionedClassId = combineToLong(cdImpl.getClassId(), cdImpl.getVersion());
            registerNestedDefinitions(cdImpl);
            final ClassDefinitionImpl currentCd = versionedDefinitions.putIfAbsent(versionedClassId, cdImpl);
            return currentCd == null ? cdImpl : currentCd;
        }
    }

    static void compress(byte[] input, DataOutput out) throws IOException {
        Deflater deflater = new Deflater();
        deflater.setLevel(Deflater.DEFAULT_COMPRESSION);
        deflater.setStrategy(Deflater.FILTERED);
        deflater.setInput(input);
        deflater.finish();
        byte[] buf = new byte[1024];
        while (!deflater.finished()) {
            int count = deflater.deflate(buf);
            out.write(buf, 0, count);
        }
        deflater.end();
    }

    static void decompress(byte[] compressedData, DataOutput out) throws IOException {
        Inflater inflater = new Inflater();
        inflater.setInput(compressedData);
        byte[] buf = new byte[1024];
        while (!inflater.finished()) {
            try {
                int count = inflater.inflate(buf);
                out.write(buf, 0, count);
            } catch (DataFormatException e) {
                throw new IOException(e);
            }
        }
        inflater.end();
    }

    static long combineToLong(int x, int y) {
        return ((long) x << 32) | ((long) y & 0xFFFFFFFFL);
    }

    static int extractInt(long value, boolean lowerBits) {
        return (lowerBits) ? (int) value : (int) (value >> 32);
    }
}
TOP

Related Classes of com.hazelcast.nio.serialization.SerializationContextImpl$PortableContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.