PageRenderTime 913ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/columba-1.0/src/columba/core/org/columba/core/main/ColumbaServer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 251 lines | 141 code | 35 blank | 75 comment | 13 complexity | 3aba78dd17774ee3f71c5ce12418f129 MD5 | raw file
  1. //The contents of this file are subject to the Mozilla Public License Version 1.1
  2. //(the "License"); you may not use this file except in compliance with the
  3. //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
  4. //
  5. //Software distributed under the License is distributed on an "AS IS" basis,
  6. //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  7. //for the specific language governing rights and
  8. //limitations under the License.
  9. //
  10. //The Original Code is "The Columba Project"
  11. //
  12. //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
  13. //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
  14. //
  15. //All Rights Reserved.
  16. package org.columba.core.main;
  17. import java.io.BufferedReader;
  18. import java.io.IOException;
  19. import java.io.InputStreamReader;
  20. import java.io.PrintWriter;
  21. import java.net.ServerSocket;
  22. import java.net.Socket;
  23. import java.net.SocketException;
  24. import java.net.SocketTimeoutException;
  25. import java.util.LinkedList;
  26. import java.util.List;
  27. import java.util.Random;
  28. import java.util.StringTokenizer;
  29. import javax.swing.JOptionPane;
  30. import org.apache.commons.cli.CommandLine;
  31. import org.apache.commons.cli.ParseException;
  32. import org.columba.core.component.ComponentManager;
  33. import org.columba.core.resourceloader.GlobalResourceLoader;
  34. import org.columba.core.shutdown.ShutdownManager;
  35. /**
  36. * Opens a server socket to manage multiple sessions of Columba capable of
  37. * passing commands to the main session.
  38. * <p>
  39. * This class is a singleton because there can only be one server per Columba
  40. * session.
  41. * <p>
  42. * Basic idea taken from www.jext.org (author Roman Guy)
  43. *
  44. * @author fdietz
  45. */
  46. public class ColumbaServer {
  47. static final String RESOURCE_PATH = "org.columba.core.i18n.dialog";
  48. /**
  49. * The anonymous user for single-user systems without user name.
  50. */
  51. protected static final String ANONYMOUS_USER = "anonymous";
  52. /**
  53. * The singleton instance of this class.
  54. */
  55. private static ColumbaServer instance;
  56. /**
  57. * Random number generator for port numbers.
  58. */
  59. private static Random random = new Random();
  60. /**
  61. * The port range Columba should use is between LOWEST_PORT and 65536.
  62. */
  63. private static final int LOWEST_PORT = 30000;
  64. /**
  65. * Server runs in its own thread.
  66. */
  67. protected Thread thread;
  68. /**
  69. * The ServerSocket used by the server.
  70. */
  71. protected ServerSocket serverSocket;
  72. /**
  73. * Constructor
  74. */
  75. protected ColumbaServer() {
  76. thread = new Thread(new Runnable() {
  77. public void run() {
  78. while (!Thread.currentThread().isInterrupted()) {
  79. try {
  80. handleClient(serverSocket.accept());
  81. } catch (SocketTimeoutException ste) {
  82. // do nothing here, just continue
  83. } catch (IOException ioe) {
  84. ioe.printStackTrace();
  85. // what to do here? we could start a new server...
  86. }
  87. }
  88. try {
  89. serverSocket.close();
  90. // cleanup: remove port number file
  91. SessionController.serializePortNumber(-1);
  92. } catch (IOException ioe) {
  93. }
  94. serverSocket = null;
  95. }
  96. }, "ColumbaServer");
  97. thread.setDaemon(true);
  98. // stop server when shutting down
  99. ShutdownManager.getInstance().register(new Runnable() {
  100. public void run() {
  101. stop();
  102. }
  103. });
  104. }
  105. /**
  106. * Starts the server.
  107. */
  108. public synchronized void start() throws IOException {
  109. if (!isRunning()) {
  110. int port;
  111. int count = 0;
  112. while (serverSocket == null) {
  113. // create random port number within range
  114. port = random.nextInt(65536 - LOWEST_PORT) + LOWEST_PORT;
  115. try {
  116. serverSocket = new ServerSocket(port);
  117. // store port number in file
  118. SessionController.serializePortNumber(port);
  119. } catch (SocketException se) { // port is in use, try next
  120. count++;
  121. if (count == 10) { // something is very wrong here
  122. JOptionPane.showMessageDialog(null,
  123. GlobalResourceLoader.getString(RESOURCE_PATH,
  124. "session", "err_10se_msg"),
  125. GlobalResourceLoader.getString(RESOURCE_PATH,
  126. "session", "err_10se_title"),
  127. JOptionPane.ERROR_MESSAGE);
  128. // this is save because the only shutdown plugin
  129. // to stop this server, the configuration isn't touched
  130. System.exit(1);
  131. }
  132. }
  133. }
  134. serverSocket.setSoTimeout(2000);
  135. thread.start();
  136. }
  137. }
  138. /**
  139. * Stops the server.
  140. */
  141. public synchronized void stop() {
  142. thread.interrupt();
  143. }
  144. /**
  145. * Check if server is already running
  146. *
  147. * @return true, if server is running. False, otherwise
  148. */
  149. public synchronized boolean isRunning() {
  150. return thread.isAlive();
  151. }
  152. /**
  153. * Handles a client connect and authentication.
  154. */
  155. protected void handleClient(Socket client) {
  156. try {
  157. // only accept client from local machine
  158. String host = client.getLocalAddress().getHostAddress();
  159. if (!(host.equals("127.0.0.1"))) {
  160. // client isn't from local machine
  161. return;
  162. }
  163. BufferedReader reader = new BufferedReader(new InputStreamReader(
  164. client.getInputStream()));
  165. String line = reader.readLine();
  166. if (!line.startsWith("Columba ")) {
  167. return;
  168. }
  169. line = reader.readLine();
  170. if (!line.startsWith("User ")) {
  171. return;
  172. }
  173. PrintWriter writer = new PrintWriter(client.getOutputStream());
  174. if (!line.substring(5).equals(
  175. System.getProperty("user.name", ANONYMOUS_USER))) {
  176. writer.write("WRONG USER\r\n");
  177. writer.close();
  178. return;
  179. }
  180. writer.write("\r\n");
  181. writer.flush();
  182. line = reader.readLine();
  183. // do something with the arguments..
  184. List list = new LinkedList();
  185. StringTokenizer st = new StringTokenizer(line, "%");
  186. while (st.hasMoreTokens()) {
  187. String tok = (String) st.nextToken();
  188. list.add(tok);
  189. }
  190. try {
  191. CommandLine commandLine = ColumbaCmdLineParser.getInstance()
  192. .parse((String[]) list.toArray(new String[0]));
  193. ComponentManager.getInstance().handleCommandLineParameters(
  194. commandLine);
  195. } catch (ParseException e) {
  196. e.printStackTrace();
  197. }
  198. } catch (IOException ioe) {
  199. ioe.printStackTrace();
  200. } finally {
  201. try {
  202. client.close();
  203. } catch (IOException ioe) {
  204. }
  205. }
  206. }
  207. /**
  208. * Returns the singleton instance of this class.
  209. */
  210. public static synchronized ColumbaServer getColumbaServer() {
  211. if (instance == null) {
  212. instance = new ColumbaServer();
  213. }
  214. return instance;
  215. }
  216. }