/hazelcast/src/main/java/com/hazelcast/nio/ascii/SocketTextReader.java

https://bitbucket.org/gabral6_gmailcom/hazelcast · Java · 181 lines · 147 code · 18 blank · 16 comment · 29 complexity · 8cdf3cc19aaa2debfb7224ba3213c369 MD5 · raw file

  1. /*
  2. * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
  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.hazelcast.nio.ascii;
  17. import com.hazelcast.impl.ascii.CommandParser;
  18. import com.hazelcast.impl.ascii.TextCommand;
  19. import com.hazelcast.impl.ascii.TextCommandConstants;
  20. import com.hazelcast.impl.ascii.TextCommandService;
  21. import com.hazelcast.impl.ascii.memcache.*;
  22. import com.hazelcast.impl.ascii.rest.HttpCommand;
  23. import com.hazelcast.impl.ascii.rest.HttpDeleteCommandParser;
  24. import com.hazelcast.impl.ascii.rest.HttpGetCommandParser;
  25. import com.hazelcast.impl.ascii.rest.HttpPostCommandParser;
  26. import com.hazelcast.logging.ILogger;
  27. import com.hazelcast.nio.Connection;
  28. import com.hazelcast.nio.IOService;
  29. import com.hazelcast.nio.SocketReader;
  30. import java.nio.ByteBuffer;
  31. import java.util.HashMap;
  32. import java.util.Map;
  33. import java.util.logging.Level;
  34. import static com.hazelcast.impl.ascii.TextCommandConstants.TextCommandType.*;
  35. public class SocketTextReader implements TextCommandConstants, SocketReader {
  36. private final static Map<String, CommandParser> mapCommandParsers = new HashMap<String, CommandParser>();
  37. static {
  38. mapCommandParsers.put("get", new GetCommandParser());
  39. mapCommandParsers.put("gets", new GetCommandParser());
  40. mapCommandParsers.put("set", new SetCommandParser(SET));
  41. mapCommandParsers.put("add", new SetCommandParser(ADD));
  42. mapCommandParsers.put("replace", new SetCommandParser(REPLACE));
  43. mapCommandParsers.put("append", new SetCommandParser(APPEND));
  44. mapCommandParsers.put("prepend", new SetCommandParser(PREPEND));
  45. mapCommandParsers.put("delete", new DeleteCommandParser());
  46. mapCommandParsers.put("quit", new SimpleCommandParser(QUIT));
  47. mapCommandParsers.put("stats", new SimpleCommandParser(STATS));
  48. mapCommandParsers.put("GET", new HttpGetCommandParser());
  49. mapCommandParsers.put("POST", new HttpPostCommandParser());
  50. mapCommandParsers.put("PUT", new HttpPostCommandParser());
  51. mapCommandParsers.put("DELETE", new HttpDeleteCommandParser());
  52. }
  53. ByteBuffer commandLine = ByteBuffer.allocate(500);
  54. boolean commandLineRead = false;
  55. TextCommand command = null;
  56. private final TextCommandService textCommandService;
  57. private final SocketTextWriter socketTextWriter;
  58. private final Connection connection;
  59. private final boolean restEnabled;
  60. private final boolean memcacheEnabled;
  61. boolean connectionTypeSet = false;
  62. long requestIdGen;
  63. private final ILogger logger;
  64. public SocketTextReader(Connection connection) {
  65. IOService ioService = connection.getConnectionManager().getIOHandler();
  66. this.textCommandService = ioService.getTextCommandService();
  67. this.socketTextWriter = (SocketTextWriter) connection.getWriteHandler().getSocketWriter();
  68. this.connection = connection;
  69. this.memcacheEnabled = ioService.isMemcacheEnabled();
  70. this.restEnabled = ioService.isRestEnabled();
  71. this.logger = ioService.getLogger(this.getClass().getName());
  72. }
  73. public void sendResponse(TextCommand command) {
  74. socketTextWriter.enqueue(command);
  75. }
  76. public void read(ByteBuffer inBuffer) {
  77. while (inBuffer.hasRemaining()) {
  78. doRead(inBuffer);
  79. }
  80. }
  81. private void doRead(ByteBuffer bb) {
  82. while (!commandLineRead && bb.hasRemaining()) {
  83. byte b = bb.get();
  84. char c = (char) b;
  85. if (c == '\n') {
  86. commandLineRead = true;
  87. } else if (c != '\r') {
  88. commandLine.put(b);
  89. }
  90. }
  91. if (commandLineRead) {
  92. if (command == null) {
  93. processCmd(toStringAndClear(commandLine));
  94. }
  95. if (command != null) {
  96. boolean complete = command.doRead(bb);
  97. if (complete) {
  98. publishRequest(command);
  99. reset();
  100. }
  101. } else {
  102. reset();
  103. }
  104. }
  105. }
  106. void reset() {
  107. command = null;
  108. commandLine.clear();
  109. commandLineRead = false;
  110. }
  111. public static String toStringAndClear(ByteBuffer bb) {
  112. if (bb == null) return "";
  113. String result = null;
  114. if (bb.position() == 0) {
  115. result = "";
  116. } else {
  117. result = new String(bb.array(), 0, bb.position());
  118. }
  119. bb.clear();
  120. return result;
  121. }
  122. public void publishRequest(TextCommand command) {
  123. // System.out.println("publishing " + command);
  124. if (!connectionTypeSet) {
  125. if (command instanceof HttpCommand) {
  126. if (!restEnabled) {
  127. connection.close();
  128. }
  129. connection.setType(Connection.Type.REST_CLIENT);
  130. } else {
  131. if (!memcacheEnabled) {
  132. connection.close();
  133. }
  134. connection.setType(Connection.Type.MEMCACHE_CLIENT);
  135. }
  136. connectionTypeSet = true;
  137. }
  138. long requestId = (command.shouldReply()) ? requestIdGen++ : -1;
  139. command.init(this, requestId);
  140. textCommandService.processRequest(command);
  141. }
  142. void processCmd(String cmd) {
  143. try {
  144. int space = cmd.indexOf(' ');
  145. String operation = (space == -1) ? cmd : cmd.substring(0, space);
  146. CommandParser commandParser = mapCommandParsers.get(operation);
  147. if (commandParser != null) {
  148. command = commandParser.parser(this, cmd, space);
  149. } else {
  150. command = new ErrorCommand(UNKNOWN);
  151. }
  152. } catch (Throwable t) {
  153. logger.log(Level.FINEST, t.getMessage(), t);
  154. command = new ErrorCommand(ERROR_CLIENT, "Invalid command : " + cmd);
  155. }
  156. }
  157. public SocketTextWriter getSocketTextWriter() {
  158. return socketTextWriter;
  159. }
  160. public void closeConnection() {
  161. connection.close();
  162. }
  163. }