diff --git a/src/main/java/org/lcdproc/lcdjava/LCD.java b/src/main/java/org/lcdproc/lcdjava/LCD.java index 1d72e4a..1a91baa 100644 --- a/src/main/java/org/lcdproc/lcdjava/LCD.java +++ b/src/main/java/org/lcdproc/lcdjava/LCD.java @@ -9,6 +9,8 @@ import java.net.Socket; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -456,25 +458,27 @@ public void menuAction(String menuId, String eventType, String value) { * Shut down the server, terminating any threads. * @throws LCDException in case of a network problem. */ + @SuppressWarnings("WeakerAccess") public void shutdown() throws LCDException { _log.debug("Shutdown requested"); if (_poller != null) { - _poller.interrupt(); - _log.debug("Waiting for LCDSocketPoller to terminate..."); try { + _log.debug("Carefully killing socket..."); + _socket.shutdownInput(); + _log.debug("Waiting for LCDSocketPoller to terminate..."); _poller.join(); - } catch (InterruptedException e) { - e.printStackTrace(); + } catch (InterruptedException | IOException e) { + _log.error(e.toString()); } } try { _log.debug("Closing socket"); - if (_socket != null && !_socket.isClosed()) + if (_socket != null) { _socket.close(); } @@ -625,38 +629,28 @@ private void parseInitString(String init) * @return the response from the server. * @throws IOException in case of a network problem. */ - private String connect(String host, int port, String clientName) - throws IOException - { + private String connect(String host, int port, String clientName) throws IOException { _socket = new Socket(host, port); BufferedReader in = new BufferedReader(new InputStreamReader( - _socket.getInputStream())); + _socket.getInputStream())); _out = new BufferedWriter(new OutputStreamWriter( - _socket.getOutputStream())); - _poller = new LCDSocketPoller(in, this); + _socket.getOutputStream())); + Semaphore serverHello = new Semaphore(1); + _poller = new LCDSocketPoller(in, this, serverHello); _poller.start(); - write(CMD_INIT); - String response = null; - - for (int i = 0; i < POLL_REPEAT && response == null; i++) - { - synchronized (this) - { - try - { - Thread.sleep(POLL); - response = _poller.getLastLine(); - } - catch (InterruptedException e) - { - // Do nothing - } + try { + if (serverHello.tryAcquire(5, TimeUnit.SECONDS)) { + String version = _poller.getLastLine(); + write(CMD_CLIENT_SET + clientName); + return version; + } else { + // Timeout => failed to connect + return null; } + } catch (InterruptedException e) { + return null; } - write(CMD_CLIENT_SET + clientName); - - return response; } /** diff --git a/src/main/java/org/lcdproc/lcdjava/LCDSocketPoller.java b/src/main/java/org/lcdproc/lcdjava/LCDSocketPoller.java index 6f1233b..ef8070d 100644 --- a/src/main/java/org/lcdproc/lcdjava/LCDSocketPoller.java +++ b/src/main/java/org/lcdproc/lcdjava/LCDSocketPoller.java @@ -2,6 +2,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.concurrent.Semaphore; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -10,24 +11,9 @@ /** * Thread that listens for data on the LCD socket. - *

Copyright (c) 2004-2005 Darren Greaves. - * @author Darren Greaves - * @version $Id: LCDSocketPoller.java,v 1.3 2008-07-06 15:38:34 boncey Exp $ */ -public class LCDSocketPoller extends Thread -{ - /** - * Version details. - */ - public static final String CVSID = - "$Id: LCDSocketPoller.java,v 1.3 2008-07-06 15:38:34 boncey Exp $"; - - private static Logger _log = LoggerFactory.getLogger(LCDSocketPoller.class); - - /** - * How often to poll for changes. - */ - private static final int POLL = 100; +class LCDSocketPoller extends Thread { + private final Logger _log = LoggerFactory.getLogger(LCDSocketPoller.class); /** * The Pattern that matches ignore/listen events. @@ -44,7 +30,7 @@ public class LCDSocketPoller extends Thread /** * The Reader to read data from. */ - private BufferedReader _in; + private final BufferedReader _in; /** * The last line of data received. @@ -55,88 +41,59 @@ public class LCDSocketPoller extends Thread /** * The listener to notify of listen/ignore events. */ - private LCDListener _listener; + private final LCDListener _listener; + + private Semaphore hello; /** * Public constructor. - * @param in the BufferedReader that will recieve data from the server. + * + * @param in the BufferedReader that will receive data from the server. * @param listener the LCDListener that gets notified of screens being - * listened to or ignored. + * listened to or ignored. */ - public LCDSocketPoller(BufferedReader in, LCDListener listener) - { + LCDSocketPoller(BufferedReader in, LCDListener listener, Semaphore hello) throws IOException { _in = in; _listener = listener; + this.hello = hello; } - /** - * Poll the socket every 100 milliseconds. - */ @Override - public void run() - { - while (!interrupted()) - { - try { - if (!_in.ready()) { - Thread.sleep(POLL); + public void run() { + try { + String line; + while ((line = _in.readLine()) != null) { + if (line.startsWith(LCD.RESPONSE_ERROR)) { + _log.warn("Got a response of " + line + + " from server"); } - if (_in.ready()) - { - _lastLine = _in.readLine(); - if (_lastLine == null) - continue; - Matcher listenIgnore = IGNORE_STATUS.matcher(_lastLine); - Matcher menuEvent = MENU_STATUS.matcher(_lastLine); - if (_lastLine.startsWith(LCD.RESPONSE_ERROR)) - { - _log.warn("Got a response of " + _lastLine + - " from server"); - } - else if (_listener != null) - { - - if (listenIgnore.matches()) - { - boolean listen = (LCD.RESPONSE_LISTEN.equals( - listenIgnore.group(1))); - try - { - int screenId = Integer.parseInt(listenIgnore.group(2)); - _listener.setListenStatus(screenId, listen); - } - catch (NumberFormatException e) - { - // Ignore - } - } - else if (menuEvent.matches()) - { - _listener.menuAction(menuEvent.group(2), menuEvent.group(1), menuEvent.group(3)); - } - } + Matcher listenIgnore = IGNORE_STATUS.matcher(line); + Matcher menuEvent = MENU_STATUS.matcher(line); + if (listenIgnore.matches()) { + boolean listen = (LCD.RESPONSE_LISTEN.equals(listenIgnore.group(1))); + int screenId = Integer.parseInt(listenIgnore.group(2)); + _listener.setListenStatus(screenId, listen); + } else if (menuEvent.matches()) { + _listener.menuAction(menuEvent.group(2), menuEvent.group(1), menuEvent.group(3)); } + synchronized (this) { + _lastLine = line; + } + hello.release(); } - catch (InterruptedException e) - { - interrupt(); - } - catch (IOException e) - { - _log.error("Caught IOException", e); - } + } catch (IOException e) { + throw new LCDException(e); } - _log.debug("Terminating"); } /** * Get the last line received non-blocking. *

Calling this clears the last line received. + * * @return the last line received. */ - synchronized String getLastLine() - { + synchronized String getLastLine() { String ret = _lastLine; _lastLine = null; return ret;