/plugins/RemoteControl/trunk/src/com/kpouer/jedit/remotecontrol/RemoteClient.java

# · Java · 234 lines · 187 code · 21 blank · 26 comment · 18 complexity · dcf18c71b398705197ee3d30059ee066 MD5 · raw file

  1. /*
  2. * jEdit - Programmer's Text Editor
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright Š 2011 Matthieu Casanova
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. package com.kpouer.jedit.remotecontrol;
  22. import com.kpouer.jedit.remotecontrol.command.ActionCommandHandler;
  23. import com.kpouer.jedit.remotecontrol.command.OptionCommandHandler;
  24. import com.kpouer.jedit.remotecontrol.command.RegisterEBMessageCommandHandler;
  25. import com.kpouer.jedit.remotecontrol.command.SingleLineCommandHandler;
  26. import com.kpouer.jedit.remotecontrol.command.UnregisterEBMessageCommandHandler;
  27. import com.kpouer.jedit.remotecontrol.serializer.Serializer;
  28. import com.kpouer.jedit.remotecontrol.welcome.NoWelcome;
  29. import com.kpouer.jedit.remotecontrol.welcome.WelcomeService;
  30. import org.gjt.sp.jedit.EBMessage;
  31. import org.gjt.sp.jedit.ServiceManager;
  32. import org.gjt.sp.jedit.jEdit;
  33. import org.gjt.sp.util.Log;
  34. import java.io.IOException;
  35. import java.nio.ByteBuffer;
  36. import java.nio.CharBuffer;
  37. import java.nio.channels.SocketChannel;
  38. import java.nio.charset.CharacterCodingException;
  39. import java.nio.charset.CharsetDecoder;
  40. import java.util.ArrayList;
  41. import java.util.Collection;
  42. import java.util.Collections;
  43. import java.util.HashSet;
  44. import java.util.LinkedList;
  45. import java.util.Properties;
  46. import java.util.Set;
  47. /**
  48. * @author Matthieu Casanova
  49. */
  50. public class RemoteClient
  51. {
  52. private final SocketChannel channel;
  53. private final LinkedList<String> messages;
  54. private final StringBuilder builder;
  55. private final Collection<MessageHandler> handlers;
  56. private final Serializer serializer;
  57. private final Properties props;
  58. /**
  59. * The messages that the client want to receive
  60. */
  61. private final Set<Class<? extends EBMessage>> registeredMessages;
  62. public RemoteClient(SocketChannel sChannel)
  63. {
  64. channel = sChannel;
  65. props = new Properties();
  66. registeredMessages = Collections.synchronizedSet(new HashSet<Class<? extends EBMessage>>());
  67. messages = new LinkedList<String>();
  68. builder = new StringBuilder();
  69. handlers = new ArrayList<MessageHandler>();
  70. String welcomeService = jEdit.getProperty("remotecontrol.welcomeservice", "");
  71. if (welcomeService.length() == 0)
  72. {
  73. handshaked();
  74. } else
  75. {
  76. WelcomeService welcome = ServiceManager.getService(WelcomeService.class, welcomeService);
  77. if (welcome == null)
  78. throw new InternalError("No welcome service by that name " + welcomeService);
  79. welcome.setClient(this);
  80. welcome.setChannel(sChannel);
  81. handlers.add(welcome);
  82. }
  83. serializer = ServiceManager.getService(Serializer.class, "xsjson");
  84. }
  85. public void registerMessage(Class<? extends EBMessage> clz)
  86. {
  87. registeredMessages.add(clz);
  88. }
  89. public void unregisterMessage(Class<? extends EBMessage> clz)
  90. {
  91. registeredMessages.remove(clz);
  92. }
  93. public Serializer getSerializer()
  94. {
  95. String serializerName = props.getProperty("serializer", "xsjson");
  96. Serializer serializer = ServiceManager.getService(Serializer.class, serializerName);
  97. if (serializer == null)
  98. {
  99. Log.log(Log.ERROR, this, "Wrong serializer " + serializerName);
  100. serializer = ServiceManager.getService(Serializer.class, "xsjson");
  101. }
  102. if (serializer == null)
  103. {
  104. throw new InternalError("No xsjson serializer !!!");
  105. }
  106. return serializer;
  107. }
  108. public void read(ByteBuffer buf)
  109. {
  110. buf.flip();
  111. CharsetDecoder decoder = RemoteServer.CHARSET.newDecoder();
  112. try
  113. {
  114. CharBuffer charBuffer = decoder.decode(buf);
  115. for (int i = 0; i < charBuffer.length(); i++)
  116. {
  117. char c = charBuffer.get(i);
  118. switch (c)
  119. {
  120. case '\n':
  121. if (builder.length() != 0)
  122. {
  123. String line = builder.toString().trim();
  124. builder.setLength(0);
  125. if (!line.isEmpty())
  126. {
  127. Log.log(Log.DEBUG, this, "Received " + line);
  128. messages.add(line);
  129. }
  130. }
  131. break;
  132. case '\r':
  133. break;
  134. default:
  135. builder.append(c);
  136. }
  137. }
  138. } catch (CharacterCodingException e)
  139. {
  140. Log.log(Log.ERROR, this, e, e);
  141. }
  142. handleMessage();
  143. }
  144. public void handshaked()
  145. {
  146. handlers.clear();
  147. handlers.add(new SingleLineCommandHandler(this));
  148. handlers.add(new ActionCommandHandler());
  149. handlers.add(new OptionCommandHandler(this));
  150. handlers.add(new RegisterEBMessageCommandHandler(this));
  151. handlers.add(new UnregisterEBMessageCommandHandler(this));
  152. handlers.add(new NoWelcome());
  153. }
  154. private void handleMessage()
  155. {
  156. while (!messages.isEmpty())
  157. {
  158. String line = messages.removeFirst();
  159. for (MessageHandler handler : handlers)
  160. {
  161. try
  162. {
  163. if (handler.accept(line))
  164. {
  165. handler.handleMessage(line);
  166. break;
  167. }
  168. } catch (Exception e)
  169. {
  170. Log.log(Log.ERROR, this, "Error while processing message " + line, e);
  171. }
  172. }
  173. }
  174. }
  175. public void sendObject(Object o)
  176. {
  177. String message = serializer.serialize(o) + "\n";
  178. byte[] bytes = message.getBytes(RemoteServer.CHARSET);
  179. sendMessage(bytes);
  180. }
  181. void sendMessage(EBMessage message)
  182. {
  183. if (registeredMessages.contains(message.getClass()))
  184. {
  185. Serializer serializer = getSerializer();
  186. String s = serializer.serialize(message) + "\n";
  187. if (RemoteServer.DEBUG)
  188. {
  189. Log.log(Log.MESSAGE, this, s);
  190. }
  191. sendMessage(s.getBytes(RemoteServer.CHARSET));
  192. }
  193. }
  194. void sendMessage(byte[] message)
  195. {
  196. try
  197. {
  198. channel.write(ByteBuffer.wrap(message));
  199. } catch (IOException e)
  200. {
  201. Log.log(Log.WARNING, this, e, e);
  202. }
  203. }
  204. public void setProperty(String key, String value)
  205. {
  206. props.setProperty(key, value);
  207. }
  208. @Override
  209. public String toString()
  210. {
  211. return "RemoteClient[" + channel.socket().getInetAddress() + ":" + channel.socket().getPort() + "]";
  212. }
  213. }