/*
* 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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* copy->TBaseDeserializer
*/
public class HeaderTBaseDeserializer {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final TProtocol protocol;
private final TMemoryInputTransport trans;
private final TBaseLocator locator;
/**
* Create a new TDeserializer. It will use the TProtocol specified by the
* factory that is passed in.
*
* @param protocolFactory Factory to create a protocol
*/
HeaderTBaseDeserializer(TProtocolFactory protocolFactory, TBaseLocator locator) {
this.trans = new TMemoryInputTransport();
this.protocol = protocolFactory.getProtocol(trans);
this.locator = locator;
}
/**
* Deserialize the Thrift object from a byte array.
*
* @param bytes The array to read from
*/
public TBase<?, ?> deserialize(byte[] bytes) throws TException {
try {
trans.reset(bytes);
Header header = readHeader();
final int validate = validate(header);
if (validate == HeaderUtils.OK) {
TBase<?, ?> base = locator.tBaseLookup(header.getType());
base.read(protocol);
return base;
}
throw new IllegalStateException("invalid validate " + validate);
} finally {
trans.clear();
protocol.reset();
}
}
public List<TBase<?, ?>> deserializeList(byte[] buffer) throws TException {
List<TBase<?, ?>> tBaseList = new ArrayList<TBase<?,?>>();
trans.reset(buffer);
try {
while (trans.getBytesRemainingInBuffer() > 0) {
Header header = readHeader();
final int validate = validate(header);
if (validate == HeaderUtils.OK) {
TBase<?, ?> base = locator.tBaseLookup(header.getType());
base.read(protocol);
tBaseList.add(base);
} else {
throw new IllegalStateException("invalid validate " + validate);
}
}
} catch (Exception e){
logger.warn("failed to deserialize.", e);
return new ArrayList<TBase<?,?>>();
} finally {
trans.clear();
protocol.reset();
}
return tBaseList;
}
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 {
final byte signature = protocol.readByte();
final byte version = protocol.readByte();
// fixed size regardless protocol
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)));
}
}