/motan-extension/serialization-extension/src/main/java/com/weibo/api/motan/serialize/ProtobufSerialization.java

https://github.com/weibocom/motan · Java · 173 lines · 134 code · 17 blank · 22 comment · 101 complexity · 6c96f92d35f996832a68cb47c4d00722 MD5 · raw file

  1. /*
  2. * Copyright 2009-2016 Weibo, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.weibo.api.motan.serialize;
  17. import com.google.protobuf.CodedInputStream;
  18. import com.google.protobuf.CodedOutputStream;
  19. import com.google.protobuf.MessageLite;
  20. import com.weibo.api.motan.codec.Serialization;
  21. import com.weibo.api.motan.core.extension.SpiMeta;
  22. import com.weibo.api.motan.exception.MotanFrameworkException;
  23. import java.io.*;
  24. import java.lang.reflect.Method;
  25. /**
  26. * protobuf序列化器,支持基本数据类型及其包装类、String、Throwable、Protobuf2/3对象
  27. *
  28. * @author zhouhaocheng
  29. */
  30. @SpiMeta(name = "protobuf")
  31. public class ProtobufSerialization implements Serialization {
  32. @Override
  33. public byte[] serialize(Object obj) throws IOException {
  34. ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
  35. // 兼容motan1 协议,对throwable使用 java ObjectOutputStream进行序列化
  36. if (Throwable.class.isAssignableFrom(obj.getClass())) {
  37. ObjectOutputStream oos = new ObjectOutputStream(baos);
  38. oos.writeObject(obj);
  39. oos.flush();
  40. } else {
  41. CodedOutputStream output = CodedOutputStream.newInstance(baos);
  42. serialize(output, obj);
  43. output.flush();
  44. }
  45. return baos.toByteArray();
  46. }
  47. @SuppressWarnings("unchecked")
  48. @Override
  49. public <T> T deserialize(byte[] bytes, Class<T> clazz) throws IOException {
  50. // 兼容motan1 协议,对throwable使用 java ObjectInputStream进行反序列化
  51. if (Throwable.class.isAssignableFrom(clazz)) {
  52. try {
  53. ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
  54. return (T) ois.readObject();
  55. } catch (ClassNotFoundException e) {
  56. throw new MotanFrameworkException(e);
  57. }
  58. } else {
  59. CodedInputStream in = CodedInputStream.newInstance(bytes);
  60. return (T) deserialize(in, clazz);
  61. }
  62. }
  63. @Override
  64. public byte[] serializeMulti(Object[] data) throws IOException {
  65. ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
  66. CodedOutputStream output = CodedOutputStream.newInstance(baos);
  67. for (Object obj : data) {
  68. serialize(output, obj);
  69. }
  70. output.flush();
  71. return baos.toByteArray();
  72. }
  73. @Override
  74. public Object[] deserializeMulti(byte[] data, Class<?>[] classes) throws IOException {
  75. CodedInputStream in = CodedInputStream.newInstance(data);
  76. Object[] objects = new Object[classes.length];
  77. for (int i = 0; i < classes.length; i++) {
  78. objects[i] = deserialize(in, classes[i]);
  79. }
  80. return objects;
  81. }
  82. protected void serialize(CodedOutputStream output, Object obj) throws IOException {
  83. if (obj == null) {
  84. output.writeBoolNoTag(true);
  85. ;
  86. } else {
  87. output.writeBoolNoTag(false);
  88. Class<?> clazz = obj.getClass();
  89. if (clazz == int.class || clazz == Integer.class) {
  90. output.writeSInt32NoTag((Integer) obj);
  91. } else if (clazz == long.class || clazz == Long.class) {
  92. output.writeSInt64NoTag((Long) obj);
  93. } else if (clazz == boolean.class || clazz == Boolean.class) {
  94. output.writeBoolNoTag((Boolean) obj);
  95. } else if (clazz == byte.class || clazz == Byte.class) {
  96. output.writeRawByte((Byte) obj);
  97. } else if (clazz == char.class || clazz == Character.class) {
  98. output.writeSInt32NoTag((Character) obj);
  99. } else if (clazz == short.class || clazz == Short.class) {
  100. output.writeSInt32NoTag((Short) obj);
  101. } else if (clazz == double.class || clazz == Double.class) {
  102. output.writeDoubleNoTag((Double) obj);
  103. } else if (clazz == float.class || clazz == Float.class) {
  104. output.writeFloatNoTag((Float) obj);
  105. } else if (clazz == String.class) {
  106. output.writeStringNoTag(obj.toString());
  107. } else if (MessageLite.class.isAssignableFrom(clazz)) {
  108. output.writeMessageNoTag((MessageLite) obj);
  109. } else {
  110. throw new IllegalArgumentException("can't serialize " + clazz);
  111. }
  112. }
  113. }
  114. protected Object deserialize(CodedInputStream in, Class<?> clazz) throws IOException {
  115. if (in.readBool()) {
  116. return null;
  117. } else {
  118. Object value;
  119. if (clazz == int.class || clazz == Integer.class) {
  120. value = in.readSInt32();
  121. } else if (clazz == long.class || clazz == Long.class) {
  122. value = in.readSInt64();
  123. } else if (clazz == boolean.class || clazz == Boolean.class) {
  124. value = in.readBool();
  125. } else if (clazz == byte.class || clazz == Byte.class) {
  126. value = in.readRawByte();
  127. } else if (clazz == char.class || clazz == Character.class) {
  128. value = (char) in.readSInt32();
  129. } else if (clazz == short.class || clazz == Short.class) {
  130. value = (short) in.readSInt32();
  131. } else if (clazz == double.class || clazz == Double.class) {
  132. value = in.readDouble();
  133. } else if (clazz == float.class || clazz == Float.class) {
  134. value = in.readFloat();
  135. } else if (clazz == String.class) {
  136. value = in.readString();
  137. } else if (MessageLite.class.isAssignableFrom(clazz)) {
  138. try {
  139. Method method = clazz.getDeclaredMethod("newBuilder", null);
  140. MessageLite.Builder builder = (MessageLite.Builder) method.invoke(null, null);
  141. in.readMessage(builder, null);
  142. value = builder.build();
  143. } catch (Exception e) {
  144. throw new MotanFrameworkException(e);
  145. }
  146. } else {
  147. throw new IllegalArgumentException("can't serialize " + clazz);
  148. }
  149. return value;
  150. }
  151. }
  152. @Override
  153. public int getSerializationNumber() {
  154. return 5;
  155. }
  156. }