/* * Copyright 2014 NAVER Corp. * * 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.navercorp.pinpoint.thrift.io; import java.util.ArrayList; import java.util.List; import org.apache.thrift.TBase; import org.apache.thrift.TException; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TMemoryInputTransport; /** * Deserialize chunked packets * * @author jaehong.kim * */ public class ChunkHeaderTBaseDeserializer { private final TProtocol protocol; private final TMemoryInputTransport trans; private final TBaseLocator locator; ChunkHeaderTBaseDeserializer(TProtocolFactory protocolFactory, TBaseLocator locator) { this.trans = new TMemoryInputTransport(); this.protocol = protocolFactory.getProtocol(trans); this.locator = locator; } public List<TBase<?, ?>> deserialize(byte[] bytes, int offset, int length) throws TException { List<TBase<?, ?>> list = new ArrayList<TBase<?, ?>>(); try { trans.reset(bytes, offset, length); final Header header = readHeader(); if(header == null) { return list; } if (locator.isChunkHeader(header.getType())) { TBase<?, ?> base; while ((base = deserialize()) != null) { list.add(base); } } else { TBase<?, ?> base = deserialize(); if (base != null) { list.add(base); } } } finally { trans.clear(); protocol.reset(); } return list; } private TBase<?, ?> deserialize() throws TException { final Header header = readHeader(); if (header == null) { return null; } final int validate = validate(header); TBase<?, ?> base = locator.tBaseLookup(header.getType()); base.read(protocol); return base; } private int validate(Header header) throws TException { final byte signature = header.getSignature(); final int result = HeaderUtils.validateSignature(signature); if (result == HeaderUtils.FAIL) { throw new TException("Invalid Signature:" + header); } return result; } private Header readHeader() throws TException { if (trans.getBytesRemainingInBuffer() < Header.HEADER_SIZE) { return null; } final byte signature = protocol.readByte(); final byte version = protocol.readByte(); final byte type1 = protocol.readByte(); final byte type2 = protocol.readByte(); final short type = bytesToShort(type1, type2); return new Header(signature, version, type); } private short bytesToShort(final byte byte1, final byte byte2) { return (short) (((byte1 & 0xff) << 8) | ((byte2 & 0xff))); } }