|
28 | 28 | import java.util.List;
|
29 | 29 | import java.util.Objects;
|
30 | 30 | import java.util.Properties;
|
| 31 | +import java.util.concurrent.ExecutorService; |
| 32 | +import java.util.concurrent.Executors; |
31 | 33 | import java.util.concurrent.TimeUnit;
|
32 | 34 | import org.slf4j.Logger;
|
33 | 35 | import org.slf4j.LoggerFactory;
|
@@ -251,12 +253,7 @@ private static class SingletonServer {
|
251 | 253 | private final Thread thread;
|
252 | 254 |
|
253 | 255 | SingletonServer(SingletonServerRunnable runnable) throws Exception {
|
254 |
| - if ("1.8".equals(System.getProperty("java.specification.version"))) { // NON-NLS |
255 |
| - thread = new Thread(null, runnable, "SIThread", 0); |
256 |
| - } else { |
257 |
| - thread = new Thread(null, runnable, "SIThread", 0, false); |
258 |
| - } |
259 |
| - |
| 256 | + thread = new Thread(null, runnable, "SIThread", 0, false); |
260 | 257 | thread.setDaemon(true);
|
261 | 258 | this.runnable = runnable;
|
262 | 259 | }
|
@@ -348,83 +345,107 @@ private static String getStreamEncoding(InputStream is) throws IOException {
|
348 | 345 | }
|
349 | 346 |
|
350 | 347 | private Void runSingletonServer() {
|
351 |
| - while (true) { |
352 |
| - try (Socket s = ss.accept(); |
353 |
| - InputStream is = s.getInputStream(); |
354 |
| - InputStreamReader isr = new InputStreamReader(is, getStreamEncoding(is)); |
355 |
| - BufferedReader in = new BufferedReader(isr)) { |
356 |
| - LOGGER.debug("Singleton server is waiting a connection"); |
357 |
| - |
358 |
| - // First read the random number |
359 |
| - String line = in.readLine(); |
360 |
| - if (line.equals(String.valueOf(randomNumber))) { |
361 |
| - line = in.readLine(); |
362 |
| - |
363 |
| - LOGGER.debug("Recieve message: {}", line); |
364 |
| - if (SI_MAGICWORD.equals(line)) { |
365 |
| - LOGGER.debug("Got Magic work"); |
366 |
| - List<String> recvArgs = new ArrayList<>(); |
367 |
| - Properties props = new Properties(); |
368 |
| - boolean arg = false; |
369 |
| - while (true) { |
370 |
| - try { |
371 |
| - line = in.readLine(); |
372 |
| - if (SI_EOF.equals(line)) { |
373 |
| - break; |
374 |
| - } else if (SI_ARG.equals(line)) { |
375 |
| - arg = true; |
376 |
| - } else if (SI_PROP.equals(line)) { |
377 |
| - arg = false; |
378 |
| - } else if (Utils.hasText(line)) { |
379 |
| - if (arg) { |
380 |
| - recvArgs.add(line); |
381 |
| - } else { |
382 |
| - String[] vals = line.split("=", 2); |
383 |
| - if (vals.length == 2) { |
384 |
| - props.put(vals[0], vals[1]); |
385 |
| - } |
386 |
| - } |
387 |
| - } |
388 |
| - } catch (IOException ioe1) { |
389 |
| - LOGGER.error("Reading singleton lock file", ioe1); |
390 |
| - } |
391 |
| - } |
392 |
| - if (siApp.canStartNewActivation(props)) { |
393 |
| - siApp.newActivation(recvArgs); |
394 |
| - LOGGER.debug("Sending ACK"); |
395 |
| - try (OutputStream os = s.getOutputStream(); |
396 |
| - PrintStream ps = new PrintStream(os, true, isr.getEncoding())) { |
397 |
| - ps.println(SI_ACK); |
398 |
| - ps.flush(); |
399 |
| - } |
400 |
| - } else { |
401 |
| - LOGGER.debug("Sending EXIT"); |
402 |
| - try (OutputStream os = s.getOutputStream(); |
403 |
| - PrintStream ps = new PrintStream(os, true, isr.getEncoding())) { |
404 |
| - ps.println(SI_EXIT); |
405 |
| - ps.flush(); |
406 |
| - } |
407 |
| - System.exit(0); |
408 |
| - } |
409 |
| - } else if (SI_STOP.equals(line)) { |
410 |
| - removeSiFile(); |
| 348 | + ExecutorService executor = Executors.newFixedThreadPool(1); |
| 349 | + |
| 350 | + try (ServerSocket serverSocket = ss) { |
| 351 | + while (!Thread.currentThread().isInterrupted()) { |
| 352 | + try { |
| 353 | + Socket socket = serverSocket.accept(); |
| 354 | + executor.submit(() -> handleClient(socket)); |
| 355 | + } catch (IOException e) { |
| 356 | + if (serverSocket.isClosed()) { |
411 | 357 | break;
|
412 | 358 | }
|
413 |
| - } else { |
414 |
| - // random number does not match |
415 |
| - // should not happen |
416 |
| - // shutdown server socket |
| 359 | + LOGGER.error("Error accepting connection", e); |
| 360 | + } |
| 361 | + } |
| 362 | + } catch (IOException e) { |
| 363 | + LOGGER.error("Error starting Singleton server", e); |
| 364 | + } finally { |
| 365 | + executor.shutdown(); |
| 366 | + } |
| 367 | + return null; |
| 368 | + } |
| 369 | + |
| 370 | + private void handleClient(Socket socket) { |
| 371 | + try (InputStream is = socket.getInputStream(); |
| 372 | + InputStreamReader isr = new InputStreamReader(is, getStreamEncoding(is)); |
| 373 | + BufferedReader in = new BufferedReader(isr)) { |
| 374 | + |
| 375 | + LOGGER.debug("Singleton server is waiting for a connection"); |
| 376 | + |
| 377 | + // First read the random number |
| 378 | + String line = in.readLine(); |
| 379 | + if (line.equals(String.valueOf(randomNumber))) { |
| 380 | + line = in.readLine(); |
| 381 | + LOGGER.debug("Receive message: {}", line); |
| 382 | + |
| 383 | + if (SI_MAGICWORD.equals(line)) { |
| 384 | + handleMagicWord(in, socket, isr); |
| 385 | + } else if (SI_STOP.equals(line)) { |
417 | 386 | removeSiFile();
|
418 | 387 | ss.close();
|
419 |
| - serverStarted = false; |
420 |
| - LOGGER.error("Unexpected error: Singleton {} disabled", stringId); |
421 |
| - return null; |
422 | 388 | }
|
423 |
| - } catch (IOException ex) { |
424 |
| - LOGGER.error("Starting Singleton server", ex); |
| 389 | + } else { |
| 390 | + handleUnexpectedError(); |
425 | 391 | }
|
| 392 | + } catch (IOException ex) { |
| 393 | + LOGGER.error("Error handling client", ex); |
426 | 394 | }
|
427 |
| - return null; |
| 395 | + } |
| 396 | + |
| 397 | + private void handleMagicWord(BufferedReader in, Socket s, InputStreamReader isr) |
| 398 | + throws IOException { |
| 399 | + List<String> args = new ArrayList<>(); |
| 400 | + Properties props = new Properties(); |
| 401 | + boolean arg = false; |
| 402 | + |
| 403 | + while (true) { |
| 404 | + String line = in.readLine(); |
| 405 | + if (SI_EOF.equals(line)) { |
| 406 | + break; |
| 407 | + } else if (SI_ARG.equals(line)) { |
| 408 | + arg = true; |
| 409 | + } else if (SI_PROP.equals(line)) { |
| 410 | + arg = false; |
| 411 | + } else if (Utils.hasText(line)) { |
| 412 | + if (arg) { |
| 413 | + args.add(line); |
| 414 | + } else { |
| 415 | + String[] vals = line.split("=", 2); |
| 416 | + if (vals.length == 2) { |
| 417 | + props.put(vals[0], vals[1]); |
| 418 | + } |
| 419 | + } |
| 420 | + } |
| 421 | + } |
| 422 | + |
| 423 | + if (siApp.canStartNewActivation(props)) { |
| 424 | + siApp.newActivation(args); |
| 425 | + LOGGER.debug("Sending ACK"); |
| 426 | + sendResponse(s, isr, SI_ACK); |
| 427 | + } else { |
| 428 | + LOGGER.debug("Sending EXIT"); |
| 429 | + sendResponse(s, isr, SI_EXIT); |
| 430 | + System.exit(0); |
| 431 | + } |
| 432 | + } |
| 433 | + |
| 434 | + private void sendResponse(Socket s, InputStreamReader isr, String response) throws IOException { |
| 435 | + try (OutputStream os = s.getOutputStream(); |
| 436 | + PrintStream ps = new PrintStream(os, true, isr.getEncoding())) { |
| 437 | + ps.println(response); |
| 438 | + ps.flush(); |
| 439 | + } |
| 440 | + } |
| 441 | + |
| 442 | + private void handleUnexpectedError() throws IOException { |
| 443 | + // random number does not match should not happen |
| 444 | + // shutdown server socket |
| 445 | + removeSiFile(); |
| 446 | + ss.close(); |
| 447 | + serverStarted = false; |
| 448 | + LOGGER.error("Unexpected error: Singleton {} disabled", stringId); |
428 | 449 | }
|
429 | 450 | }
|
430 | 451 | }
|
0 commit comments