/* * Copyright (c) 2015-2016, Christoph Engelbert (aka noctarius) and * contributors. 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.noctarius.tengi.spi.serialization.impl; import com.noctarius.tengi.core.serialization.codec.Decoder; import com.noctarius.tengi.core.serialization.codec.Encoder; import com.noctarius.tengi.core.serialization.debugger.SerializationDebugger; import com.noctarius.tengi.spi.buffer.MemoryBuffer; import com.noctarius.tengi.spi.buffer.ReadableMemoryBuffer; import com.noctarius.tengi.spi.buffer.WritableMemoryBuffer; import com.noctarius.tengi.spi.buffer.impl.MemoryBufferFactory; import com.noctarius.tengi.spi.pooling.ObjectPool; import com.noctarius.tengi.spi.pooling.PooledObject; import com.noctarius.tengi.spi.serialization.Protocol; import com.noctarius.tengi.spi.serialization.Serializer; import com.noctarius.tengi.spi.serialization.codec.AutoClosableDecoder; import com.noctarius.tengi.spi.serialization.codec.AutoClosableEncoder; import com.noctarius.tengi.spi.serialization.codec.impl.DefaultCodec; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; public class DefaultSerializer implements Serializer { private final ObjectPool<DefaultCodec> codecPool; private final Protocol protocol; public DefaultSerializer(Protocol protocol) { this.protocol = protocol; this.codecPool = ObjectPool.create(new CodecObjectHandler(protocol), 100); } @Override public Protocol getProtocol() { return protocol; } @Override public <O> O readObject(String fieldName, Decoder decoder) throws Exception { if (!SerializationDebugger.Debugger.ENABLED) { return decoder.readObject(); } else { try { return decoder.readObject(fieldName); } catch (Exception e) { SerializationDebugger debugger = SerializationDebugger.instance(); debugger.fixFramesToStackTrace(e); throw e; } } } @Override public <O> MemoryBuffer writeObject(String fieldName, O object) throws Exception { PooledObject<DefaultCodec> po = codecPool.acquire(); try { if (!SerializationDebugger.Debugger.ENABLED) { ByteBuf buffer = Unpooled.buffer(); MemoryBuffer memoryBuffer = MemoryBufferFactory.create(buffer); DefaultCodec codec = po.getObject().setMemoryBuffer(memoryBuffer); writeObject(fieldName, object, codec); return memoryBuffer; } else { try { ByteBuf buffer = Unpooled.buffer(); MemoryBuffer memoryBuffer = MemoryBufferFactory.create(buffer); DefaultCodec codec = po.getObject().setMemoryBuffer(memoryBuffer); writeObject("object", object, codec); return memoryBuffer; } catch (Exception e) { SerializationDebugger debugger = SerializationDebugger.instance(); debugger.fixFramesToStackTrace(e); throw e; } } } finally { codecPool.release(po); } } @Override public <O> void writeObject(String fieldName, O object, Encoder encoder) throws Exception { if (!SerializationDebugger.Debugger.ENABLED) { encoder.writeObject(fieldName, object); } else { try { encoder.writeObject(fieldName, object); } catch (Exception e) { SerializationDebugger debugger = SerializationDebugger.instance(); debugger.fixFramesToStackTrace(e); throw e; } } } @Override public AutoClosableEncoder retrieveEncoder(MemoryBuffer memoryBuffer) { PooledObject<DefaultCodec> pooledObject = codecPool.acquire((codec) -> codec.setMemoryBuffer(memoryBuffer)); return new AutoClosableCodecDelegate(pooledObject); } @Override public AutoClosableDecoder retrieveDecoder(MemoryBuffer memoryBuffer) { PooledObject<DefaultCodec> pooledObject = codecPool.acquire((codec) -> codec.setMemoryBuffer(memoryBuffer)); return new AutoClosableCodecDelegate(pooledObject); } private final class AutoClosableCodecDelegate implements AutoClosableDecoder, AutoClosableEncoder { private final PooledObject<DefaultCodec> pooledObject; private final DefaultCodec defaultCodec; private AutoClosableCodecDelegate(PooledObject<DefaultCodec> pooledObject) { this.pooledObject = pooledObject; this.defaultCodec = pooledObject.getObject(); } @Override public void readBytes(byte[] bytes) { defaultCodec.readBytes(bytes); } @Override public void readBytes(byte[] bytes, int offset, int length) { defaultCodec.readBytes(bytes, offset, length); } @Override public boolean readBoolean() { return defaultCodec.readBoolean(); } @Override public boolean[] readBitSet() { return defaultCodec.readBitSet(); } @Override public byte readByte() { return defaultCodec.readByte(); } @Override public short readUnsignedByte() { return defaultCodec.readUnsignedByte(); } @Override public short readShort() { return defaultCodec.readShort(); } @Override public char readChar() { return defaultCodec.readChar(); } @Override public int readInt32() { return defaultCodec.readInt32(); } @Override public int readCompressedInt32() { return defaultCodec.readCompressedInt32(); } @Override public long readInt64() { return defaultCodec.readInt64(); } @Override public long readCompressedInt64() { return defaultCodec.readCompressedInt64(); } @Override public float readFloat() { return defaultCodec.readFloat(); } @Override public double readDouble() { return defaultCodec.readDouble(); } @Override public String readString() { return defaultCodec.readString(); } @Override public <O> O readObject() throws Exception { return defaultCodec.readObject(); } @Override public <O> O readNullableObject() throws Exception { return defaultCodec.readNullableObject(); } @Override public ReadableMemoryBuffer getReadableMemoryBuffer() { return defaultCodec.getReadableMemoryBuffer(); } @Override public void writeBytes(byte[] bytes) { defaultCodec.writeBytes(bytes); } @Override public void writeBytes(byte[] bytes, int offset, int length) { defaultCodec.writeBytes(bytes, offset, length); } @Override public void writeBoolean(boolean value) { defaultCodec.writeBoolean(value); } @Override public void writeBitSet(boolean[] values) { defaultCodec.writeBitSet(values); } @Override public void writeByte(int value) { defaultCodec.writeByte(value); } @Override public void writeUnsignedByte(short value) { defaultCodec.writeUnsignedByte(value); } @Override public void writeShort(short value) { defaultCodec.writeShort(value); } @Override public void writeChar(char value) { defaultCodec.writeChar(value); } @Override public void writeInt32(int value) { defaultCodec.writeInt32(value); } @Override public void writeCompressedInt32(int value) { defaultCodec.writeCompressedInt32(value); } @Override public void writeInt64(long value) { defaultCodec.writeInt64(value); } @Override public void writeCompressedInt64(long value) { defaultCodec.writeCompressedInt64(value); } @Override public void writeFloat(float value) { defaultCodec.writeFloat(value); } @Override public void writeDouble(double value) { defaultCodec.writeDouble(value); } @Override public void writeString(String value) { defaultCodec.writeString(value); } @Override public void writeObject(Object object) throws Exception { defaultCodec.writeObject(object); } @Override public void writeNullableObject(Object object) throws Exception { defaultCodec.writeNullableObject(object); } @Override public WritableMemoryBuffer getWritableMemoryBuffer() { return defaultCodec.getWritableMemoryBuffer(); } @Override public void close() throws Exception { codecPool.release(pooledObject); } } }