/* * Copyright 2016-present Facebook, Inc. * * 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.facebook.buck.slb; import com.facebook.buck.log.Logger; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import org.apache.thrift.TBase; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TJSONProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.protocol.TSimpleJSONProtocol; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; public final class ThriftUtil { private static final Logger LOGGER = Logger.get(ThriftUtil.class); private ThriftUtil() { // Should not be instantiable. } public static TProtocolFactory getProtocolFactory(ThriftProtocol protocol) { // TODO(ruibm): Check whether the Factories are thread safe so we can static initialize // them just once. switch (protocol) { case JSON: return new TJSONProtocol.Factory(); case COMPACT: return new TCompactProtocol.Factory(); case BINARY: return new TBinaryProtocol.Factory(); default: throw new IllegalArgumentException( String.format("Unknown ThriftProtocol [%s].", protocol.toString())); } } public static TProtocol newProtocolInstance(ThriftProtocol protocol, TTransport transport) { return getProtocolFactory(protocol).getProtocol(transport); } public static void serialize(ThriftProtocol protocol, TBase<?, ?> source, OutputStream stream) throws ThriftException { try (TTransport transport = new TIOStreamTransport(stream)) { TProtocol thriftProtocol = getProtocolFactory(protocol).getProtocol(transport); try { source.write(thriftProtocol); } catch (TException e) { throw new ThriftException(e); } } } public static byte[] serialize(ThriftProtocol protocol, TBase<?, ?> source) throws ThriftException { TSerializer deserializer = new TSerializer(getProtocolFactory(protocol)); try { return deserializer.serialize(source); } catch (TException e) { throw new ThriftException(e); } } public static ByteBuffer serializeToByteBuffer(ThriftProtocol protocol, TBase<?, ?> source) throws ThriftException { TSerializer deserializer = new TSerializer(getProtocolFactory(protocol)); try { return ByteBuffer.wrap(deserializer.serialize(source)); } catch (TException e) { throw new ThriftException(e); } } public static void deserialize(ThriftProtocol protocol, byte[] source, TBase<?, ?> dest) throws ThriftException { TDeserializer deserializer = new TDeserializer(getProtocolFactory(protocol)); dest.clear(); try { deserializer.deserialize(dest, source); } catch (TException e) { throw new ThriftException(e); } } public static void deserialize(ThriftProtocol protocol, InputStream source, TBase<?, ?> dest) throws ThriftException { try (TIOStreamTransport responseTransport = new TIOStreamTransport(source)) { TProtocol responseProtocol = newProtocolInstance(protocol, responseTransport); dest.read(responseProtocol); } catch (TException e) { throw new ThriftException(e); } } public static String thriftToDebugJson(TBase<?, ?> thriftObject) { TSerializer serializer = new TSerializer(new TSimpleJSONProtocol.Factory()); try { return new String(serializer.serialize(thriftObject)); } catch (TException e) { LOGGER.error( e, String.format( "Failed trying to serialize type [%s] to debug JSON.", thriftObject.getClass().getName())); return "FAILED_TO_DESERIALIZE"; } } }