001/* 002 * This file is part of the Kompics component model runtime. 003 * 004 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS) 005 * Copyright (C) 2009 Royal Institute of Technology (KTH) 006 * 007 * This program is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU General Public License 009 * as published by the Free Software Foundation; either version 2 010 * of the License, or (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with this program; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020 */ 021package se.sics.kompics.network.netty.serialization; 022 023import java.util.Optional; 024import com.google.protobuf.ExtensionRegistry; 025import com.google.protobuf.InvalidProtocolBufferException; 026import com.google.protobuf.MessageLite; 027import io.netty.buffer.ByteBuf; 028 029/** 030 * 031 * @author Lars Kroll {@literal <[email protected]>} 032 */ 033public class ProtobufSerializer implements Serializer { 034 035 private static final boolean HAS_PARSER; 036 037 static { 038 boolean hasParser = false; 039 try { 040 // MessageLite.getParsetForType() is not available until protobuf 2.5.0. 041 MessageLite.class.getDeclaredMethod("getParserForType"); 042 hasParser = true; 043 } catch (Throwable t) { 044 // Ignore 045 } 046 047 HAS_PARSER = hasParser; 048 } 049 050 private final MessageLite prototype; 051 private final ExtensionRegistry extensionRegistry; 052 053 public ProtobufSerializer(MessageLite prototype) { 054 this(prototype, null); 055 } 056 057 public ProtobufSerializer(MessageLite prototype, ExtensionRegistry extensionRegistry) { 058 if (prototype == null) { 059 throw new NullPointerException("prototype"); 060 } 061 this.prototype = prototype.getDefaultInstanceForType(); 062 this.extensionRegistry = extensionRegistry; 063 } 064 065 @Override 066 public int identifier() { 067 return 4; 068 } 069 070 @Override 071 public void toBinary(Object msg, ByteBuf buf) { 072 if (msg instanceof MessageLite) { 073 byte[] bytes = ((MessageLite) msg).toByteArray(); 074 buf.writeBytes(bytes); 075 return; 076 } 077 if (msg instanceof MessageLite.Builder) { 078 byte[] bytes = ((MessageLite.Builder) msg).build().toByteArray(); 079 buf.writeBytes(bytes); 080 return; 081 } 082 } 083 084 @Override 085 public Object fromBinary(ByteBuf msg, Optional<Object> hint) { 086 final byte[] array; 087 final int offset; 088 final int length = msg.readableBytes(); 089 if (msg.hasArray()) { 090 array = msg.array(); 091 offset = msg.arrayOffset() + msg.readerIndex(); 092 } else { 093 array = new byte[length]; 094 msg.getBytes(msg.readerIndex(), array, 0, length); 095 offset = 0; 096 } 097 098 Object o = null; 099 try { 100 if (extensionRegistry == null) { 101 if (HAS_PARSER) { 102 o = prototype.getParserForType().parseFrom(array, offset, length); 103 } else { 104 o = prototype.newBuilderForType().mergeFrom(array, offset, length).build(); 105 } 106 } else { 107 if (HAS_PARSER) { 108 o = prototype.getParserForType().parseFrom(array, offset, length, extensionRegistry); 109 } else { 110 o = prototype.newBuilderForType().mergeFrom(array, offset, length, extensionRegistry).build(); 111 } 112 } 113 } catch (InvalidProtocolBufferException ex) { 114 Serializers.LOG.error("ProtobufSerializer: Couldn't deserialize object.", ex); 115 } 116 117 return o; 118 } 119 120}