PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/rocketmq-remoting/src/main/java/com/alibaba/rocketmq/remoting/protocol/RemotingCommand.java

https://gitlab.com/xialeizhou/RocketMQ
Java | 506 lines | 326 code | 131 blank | 49 comment | 49 complexity | eb382a60bc549ce16130996a78758bca MD5 | raw file
  1. /**
  2. * Copyright (C) 2010-2013 Alibaba Group Holding Limited
  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.alibaba.rocketmq.remoting.protocol;
  17. import java.lang.annotation.Annotation;
  18. import java.lang.reflect.Field;
  19. import java.lang.reflect.Modifier;
  20. import java.nio.ByteBuffer;
  21. import java.util.HashMap;
  22. import java.util.concurrent.atomic.AtomicInteger;
  23. import com.alibaba.fastjson.annotation.JSONField;
  24. import com.alibaba.rocketmq.remoting.CommandCustomHeader;
  25. import com.alibaba.rocketmq.remoting.annotation.CFNotNull;
  26. import com.alibaba.rocketmq.remoting.exception.RemotingCommandException;
  27. /**
  28. * Remoting模块中,服务器与客户端通过传递RemotingCommand来交互
  29. *
  30. * @author shijia.wxr<vintage.wang@gmail.com>
  31. * @since 2013-7-13
  32. */
  33. public class RemotingCommand {
  34. public static String RemotingVersionKey = "rocketmq.remoting.version";
  35. private static volatile int ConfigVersion = -1;
  36. private static AtomicInteger RequestId = new AtomicInteger(0);
  37. private static final int RPC_TYPE = 0; // 0, REQUEST_COMMAND
  38. // 1, RESPONSE_COMMAND
  39. private static final int RPC_ONEWAY = 1; // 0, RPC
  40. // 1, Oneway
  41. /**
  42. * Header 部分
  43. */
  44. private int code;
  45. private LanguageCode language = LanguageCode.JAVA;
  46. private int version = 0;
  47. private int opaque = RequestId.getAndIncrement();
  48. private int flag = 0;
  49. private String remark;
  50. private HashMap<String, String> extFields;
  51. private transient CommandCustomHeader customHeader;
  52. /**
  53. * Body 部分
  54. */
  55. private transient byte[] body;
  56. protected RemotingCommand() {
  57. }
  58. public static RemotingCommand createRequestCommand(int code, CommandCustomHeader customHeader) {
  59. RemotingCommand cmd = new RemotingCommand();
  60. cmd.setCode(code);
  61. cmd.customHeader = customHeader;
  62. setCmdVersion(cmd);
  63. return cmd;
  64. }
  65. public static RemotingCommand createResponseCommand(Class<? extends CommandCustomHeader> classHeader) {
  66. RemotingCommand cmd =
  67. createResponseCommand(RemotingSysResponseCode.SYSTEM_ERROR, "not set any response code",
  68. classHeader);
  69. return cmd;
  70. }
  71. public static RemotingCommand createResponseCommand(int code, String remark) {
  72. return createResponseCommand(code, remark, null);
  73. }
  74. /**
  75. * 只有通信层内部会调用,业务不会调用
  76. */
  77. public static RemotingCommand createResponseCommand(int code, String remark,
  78. Class<? extends CommandCustomHeader> classHeader) {
  79. RemotingCommand cmd = new RemotingCommand();
  80. cmd.markResponseType();
  81. cmd.setCode(code);
  82. cmd.setRemark(remark);
  83. setCmdVersion(cmd);
  84. if (classHeader != null) {
  85. try {
  86. CommandCustomHeader objectHeader = classHeader.newInstance();
  87. cmd.customHeader = objectHeader;
  88. }
  89. catch (InstantiationException e) {
  90. return null;
  91. }
  92. catch (IllegalAccessException e) {
  93. return null;
  94. }
  95. }
  96. return cmd;
  97. }
  98. private static void setCmdVersion(RemotingCommand cmd) {
  99. if (ConfigVersion >= 0) {
  100. cmd.setVersion(ConfigVersion);
  101. }
  102. else {
  103. String v = System.getProperty(RemotingVersionKey);
  104. if (v != null) {
  105. int value = Integer.parseInt(v);
  106. cmd.setVersion(value);
  107. ConfigVersion = value;
  108. }
  109. }
  110. }
  111. public void makeCustomHeaderToNet() {
  112. if (this.customHeader != null) {
  113. Field[] fields = this.customHeader.getClass().getDeclaredFields();
  114. if (null == this.extFields) {
  115. this.extFields = new HashMap<String, String>();
  116. }
  117. for (Field field : fields) {
  118. if (!Modifier.isStatic(field.getModifiers())) {
  119. String name = field.getName();
  120. if (!name.startsWith("this")) {
  121. Object value = null;
  122. try {
  123. field.setAccessible(true);
  124. value = field.get(this.customHeader);
  125. }
  126. catch (IllegalArgumentException e) {
  127. }
  128. catch (IllegalAccessException e) {
  129. }
  130. if (value != null) {
  131. this.extFields.put(name, value.toString());
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. public CommandCustomHeader readCustomHeader() {
  139. return customHeader;
  140. }
  141. public void writeCustomHeader(CommandCustomHeader customHeader) {
  142. this.customHeader = customHeader;
  143. }
  144. private static final String StringName = String.class.getCanonicalName();//
  145. private static final String IntegerName1 = Integer.class.getCanonicalName();//
  146. private static final String IntegerName2 = int.class.getCanonicalName();//
  147. private static final String LongName1 = Long.class.getCanonicalName();//
  148. private static final String LongName2 = long.class.getCanonicalName();//
  149. private static final String BooleanName1 = Boolean.class.getCanonicalName();//
  150. private static final String BooleanName2 = boolean.class.getCanonicalName();//
  151. private static final String DoubleName1 = Double.class.getCanonicalName();//
  152. private static final String DoubleName2 = double.class.getCanonicalName();//
  153. public CommandCustomHeader decodeCommandCustomHeader(Class<? extends CommandCustomHeader> classHeader)
  154. throws RemotingCommandException {
  155. if (this.extFields != null) {
  156. CommandCustomHeader objectHeader;
  157. try {
  158. objectHeader = classHeader.newInstance();
  159. }
  160. catch (InstantiationException e) {
  161. return null;
  162. }
  163. catch (IllegalAccessException e) {
  164. return null;
  165. }
  166. // 检查返回对象是否有效
  167. Field[] fields = objectHeader.getClass().getDeclaredFields();
  168. for (Field field : fields) {
  169. if (!Modifier.isStatic(field.getModifiers())) {
  170. String fieldName = field.getName();
  171. if (!fieldName.startsWith("this")) {
  172. try {
  173. String value = this.extFields.get(fieldName);
  174. if (null == value) {
  175. Annotation annotation = field.getAnnotation(CFNotNull.class);
  176. if (annotation != null) {
  177. throw new RemotingCommandException("the custom field <" + fieldName
  178. + "> is null");
  179. }
  180. continue;
  181. }
  182. field.setAccessible(true);
  183. String type = field.getType().getCanonicalName();
  184. Object valueParsed = null;
  185. if (type.equals(StringName)) {
  186. valueParsed = value;
  187. }
  188. else if (type.equals(IntegerName1) || type.equals(IntegerName2)) {
  189. valueParsed = Integer.parseInt(value);
  190. }
  191. else if (type.equals(LongName1) || type.equals(LongName2)) {
  192. valueParsed = Long.parseLong(value);
  193. }
  194. else if (type.equals(BooleanName1) || type.equals(BooleanName2)) {
  195. valueParsed = Boolean.parseBoolean(value);
  196. }
  197. else if (type.equals(DoubleName1) || type.equals(DoubleName2)) {
  198. valueParsed = Double.parseDouble(value);
  199. }
  200. else {
  201. throw new RemotingCommandException("the custom field <" + fieldName
  202. + "> type is not supported");
  203. }
  204. field.set(objectHeader, valueParsed);
  205. }
  206. catch (Throwable e) {
  207. }
  208. }
  209. }
  210. }
  211. objectHeader.checkFields();
  212. return objectHeader;
  213. }
  214. return null;
  215. }
  216. private byte[] buildHeader() {
  217. this.makeCustomHeaderToNet();
  218. return RemotingSerializable.encode(this);
  219. }
  220. public ByteBuffer encode() {
  221. // 1> header length size
  222. int length = 4;
  223. // 2> header data length
  224. byte[] headerData = this.buildHeader();
  225. length += headerData.length;
  226. // 3> body data length
  227. if (this.body != null) {
  228. length += body.length;
  229. }
  230. ByteBuffer result = ByteBuffer.allocate(4 + length);
  231. // length
  232. result.putInt(length);
  233. // header length
  234. result.putInt(headerData.length);
  235. // header data
  236. result.put(headerData);
  237. // body data;
  238. if (this.body != null) {
  239. result.put(this.body);
  240. }
  241. result.flip();
  242. return result;
  243. }
  244. public ByteBuffer encodeHeader() {
  245. return encodeHeader(this.body != null ? this.body.length : 0);
  246. }
  247. /**
  248. * 只打包Header,body部分独立传输
  249. */
  250. public ByteBuffer encodeHeader(final int bodyLength) {
  251. // 1> header length size
  252. int length = 4;
  253. // 2> header data length
  254. byte[] headerData = this.buildHeader();
  255. length += headerData.length;
  256. // 3> body data length
  257. length += bodyLength;
  258. ByteBuffer result = ByteBuffer.allocate(4 + length - bodyLength);
  259. // length
  260. result.putInt(length);
  261. // header length
  262. result.putInt(headerData.length);
  263. // header data
  264. result.put(headerData);
  265. result.flip();
  266. return result;
  267. }
  268. public static RemotingCommand decode(final byte[] array) {
  269. ByteBuffer byteBuffer = ByteBuffer.wrap(array);
  270. return decode(byteBuffer);
  271. }
  272. public static RemotingCommand decode(final ByteBuffer byteBuffer) {
  273. int length = byteBuffer.limit();
  274. int headerLength = byteBuffer.getInt();
  275. byte[] headerData = new byte[headerLength];
  276. byteBuffer.get(headerData);
  277. int bodyLength = length - 4 - headerLength;
  278. byte[] bodyData = null;
  279. if (bodyLength > 0) {
  280. bodyData = new byte[bodyLength];
  281. byteBuffer.get(bodyData);
  282. }
  283. RemotingCommand cmd = RemotingSerializable.decode(headerData, RemotingCommand.class);
  284. cmd.body = bodyData;
  285. return cmd;
  286. }
  287. public void markResponseType() {
  288. int bits = 1 << RPC_TYPE;
  289. this.flag |= bits;
  290. }
  291. @JSONField(serialize = false)
  292. public boolean isResponseType() {
  293. int bits = 1 << RPC_TYPE;
  294. return (this.flag & bits) == bits;
  295. }
  296. public void markOnewayRPC() {
  297. int bits = 1 << RPC_ONEWAY;
  298. this.flag |= bits;
  299. }
  300. @JSONField(serialize = false)
  301. public boolean isOnewayRPC() {
  302. int bits = 1 << RPC_ONEWAY;
  303. return (this.flag & bits) == bits;
  304. }
  305. public int getCode() {
  306. return code;
  307. }
  308. public void setCode(int code) {
  309. this.code = code;
  310. }
  311. @JSONField(serialize = false)
  312. public RemotingCommandType getType() {
  313. if (this.isResponseType()) {
  314. return RemotingCommandType.RESPONSE_COMMAND;
  315. }
  316. return RemotingCommandType.REQUEST_COMMAND;
  317. }
  318. public LanguageCode getLanguage() {
  319. return language;
  320. }
  321. public void setLanguage(LanguageCode language) {
  322. this.language = language;
  323. }
  324. public int getVersion() {
  325. return version;
  326. }
  327. public void setVersion(int version) {
  328. this.version = version;
  329. }
  330. public int getOpaque() {
  331. return opaque;
  332. }
  333. public void setOpaque(int opaque) {
  334. this.opaque = opaque;
  335. }
  336. public int getFlag() {
  337. return flag;
  338. }
  339. public void setFlag(int flag) {
  340. this.flag = flag;
  341. }
  342. public String getRemark() {
  343. return remark;
  344. }
  345. public void setRemark(String remark) {
  346. this.remark = remark;
  347. }
  348. public byte[] getBody() {
  349. return body;
  350. }
  351. public void setBody(byte[] body) {
  352. this.body = body;
  353. }
  354. public HashMap<String, String> getExtFields() {
  355. return extFields;
  356. }
  357. public void setExtFields(HashMap<String, String> extFields) {
  358. this.extFields = extFields;
  359. }
  360. public static int createNewRequestId() {
  361. return RequestId.incrementAndGet();
  362. }
  363. public void addExtField(String key, String value) {
  364. if (null == extFields) {
  365. extFields = new HashMap<String, String>();
  366. }
  367. extFields.put(key, value);
  368. }
  369. @Override
  370. public String toString() {
  371. return "RemotingCommand [code=" + code + ", language=" + language + ", version=" + version
  372. + ", opaque=" + opaque + ", flag(B)=" + Integer.toBinaryString(flag) + ", remark=" + remark
  373. + ", extFields=" + extFields + "]";
  374. }
  375. }