Skip to content

Commit 7ae664a

Browse files
cliniquelsiepel
authored andcommitted
[gce] Fix NullPointerException (openhab#17430)
* Remove @NonNullByDefault({}) annotations to avoid NPE Signed-off-by: Gaël L'hopital <[email protected]>
1 parent 2f6db50 commit 7ae664a

File tree

1 file changed

+45
-40
lines changed

1 file changed

+45
-40
lines changed

bundles/org.openhab.binding.gce/src/main/java/org/openhab/binding/gce/internal/handler/Ipx800DeviceConnector.java

+45-40
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import java.io.PrintWriter;
1919
import java.net.Socket;
2020
import java.net.SocketTimeoutException;
21+
import java.util.Optional;
2122

2223
import org.eclipse.jdt.annotation.NonNullByDefault;
23-
import org.eclipse.jdt.annotation.Nullable;
2424
import org.openhab.binding.gce.internal.model.M2MMessageParser;
2525
import org.openhab.core.thing.ThingUID;
2626
import org.slf4j.Logger;
@@ -35,19 +35,20 @@
3535
*/
3636
@NonNullByDefault
3737
public class Ipx800DeviceConnector extends Thread {
38-
private final Logger logger = LoggerFactory.getLogger(Ipx800DeviceConnector.class);
3938
private static final int DEFAULT_SOCKET_TIMEOUT_MS = 5000;
4039
private static final int DEFAULT_RECONNECT_TIMEOUT_MS = 5000;
4140
private static final int MAX_KEEPALIVE_FAILURE = 3;
4241
private static final String ENDL = "\r\n";
4342

43+
private final Logger logger = LoggerFactory.getLogger(Ipx800DeviceConnector.class);
44+
4445
private final String hostname;
4546
private final int portNumber;
46-
private @Nullable M2MMessageParser parser;
4747

48-
private @NonNullByDefault({}) Socket client;
49-
private @NonNullByDefault({}) BufferedReader in;
50-
private @NonNullByDefault({}) PrintWriter out;
48+
private Optional<M2MMessageParser> messageParser = Optional.empty();
49+
private Optional<Socket> socket = Optional.empty();
50+
private Optional<BufferedReader> input = Optional.empty();
51+
private Optional<PrintWriter> output = Optional.empty();
5152

5253
private int failedKeepalive = 0;
5354
private boolean waitingKeepaliveResponse = false;
@@ -60,9 +61,11 @@ public Ipx800DeviceConnector(String hostname, int portNumber, ThingUID uid) {
6061
}
6162

6263
public synchronized void send(String message) {
63-
logger.debug("Sending '{}' to Ipx800", message);
64-
out.write(message + ENDL);
65-
out.flush();
64+
output.ifPresentOrElse(out -> {
65+
logger.debug("Sending '{}' to Ipx800", message);
66+
out.write(message + ENDL);
67+
out.flush();
68+
}, () -> logger.warn("Trying to send '{}' while the output stream is closed.", message));
6669
}
6770

6871
/**
@@ -72,12 +75,15 @@ public synchronized void send(String message) {
7275
*/
7376
private void connect() throws IOException {
7477
disconnect();
75-
logger.debug("Connecting {}:{}...", hostname, portNumber);
76-
client = new Socket(hostname, portNumber);
77-
client.setSoTimeout(DEFAULT_SOCKET_TIMEOUT_MS);
78-
client.getInputStream().skip(client.getInputStream().available());
79-
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
80-
out = new PrintWriter(client.getOutputStream(), true);
78+
79+
logger.debug("Connecting to {}:{}...", hostname, portNumber);
80+
Socket socket = new Socket(hostname, portNumber);
81+
socket.setSoTimeout(DEFAULT_SOCKET_TIMEOUT_MS);
82+
socket.getInputStream().skip(socket.getInputStream().available());
83+
this.socket = Optional.of(socket);
84+
85+
input = Optional.of(new BufferedReader(new InputStreamReader(socket.getInputStream())));
86+
output = Optional.of(new PrintWriter(socket.getOutputStream(), true));
8187
}
8288

8389
/**
@@ -86,24 +92,25 @@ private void connect() throws IOException {
8692
private void disconnect() {
8793
logger.debug("Disconnecting");
8894

89-
if (in != null) {
95+
input.ifPresent(in -> {
9096
try {
9197
in.close();
9298
} catch (IOException ignore) {
9399
}
94-
this.in = null;
95-
}
96-
if (out != null) {
97-
out.close();
98-
this.out = null;
99-
}
100-
if (client != null) {
100+
input = Optional.empty();
101+
});
102+
103+
output.ifPresent(PrintWriter::close);
104+
output = Optional.empty();
105+
106+
socket.ifPresent(client -> {
101107
try {
102108
client.close();
103109
} catch (IOException ignore) {
104110
}
105-
this.client = null;
106-
}
111+
socket = Optional.empty();
112+
});
113+
107114
logger.debug("Disconnected");
108115
}
109116

@@ -120,7 +127,7 @@ public void dispose() {
120127
* If we don't receive the update maxKeepAliveFailure time, the connection is closed and reopened
121128
*/
122129
private void sendKeepalive() {
123-
if (out != null) {
130+
output.ifPresent(out -> {
124131
if (waitingKeepaliveResponse) {
125132
failedKeepalive++;
126133
logger.debug("Sending keepalive, attempt {}", failedKeepalive);
@@ -131,7 +138,7 @@ private void sendKeepalive() {
131138
out.println("GetIn01");
132139
out.flush();
133140
waitingKeepaliveResponse = true;
134-
}
141+
});
135142
}
136143

137144
@Override
@@ -144,15 +151,15 @@ public void run() {
144151
if (failedKeepalive > MAX_KEEPALIVE_FAILURE) {
145152
throw new IOException("Max keep alive attempts has been reached");
146153
}
147-
try {
148-
String command = in.readLine();
149-
waitingKeepaliveResponse = false;
150-
if (parser != null) {
151-
parser.unsolicitedUpdate(command);
154+
input.ifPresent(in -> {
155+
try {
156+
String command = in.readLine();
157+
waitingKeepaliveResponse = false;
158+
messageParser.ifPresent(parser -> parser.unsolicitedUpdate(command));
159+
} catch (IOException e) {
160+
handleException(e);
152161
}
153-
} catch (SocketTimeoutException e) {
154-
handleException(e);
155-
}
162+
});
156163
}
157164
disconnect();
158165
} catch (IOException e) {
@@ -171,15 +178,13 @@ private void handleException(Exception e) {
171178
sendKeepalive();
172179
return;
173180
} else if (e instanceof IOException) {
174-
logger.warn("Communication error : '{}', will retry in {} ms", e, DEFAULT_RECONNECT_TIMEOUT_MS);
175-
}
176-
if (parser != null) {
177-
parser.errorOccurred(e);
181+
logger.warn("Communication error: '{}'. Will retry in {} ms", e, DEFAULT_RECONNECT_TIMEOUT_MS);
178182
}
183+
messageParser.ifPresent(parser -> parser.errorOccurred(e));
179184
}
180185
}
181186

182187
public void setParser(M2MMessageParser parser) {
183-
this.parser = parser;
188+
this.messageParser = Optional.of(parser);
184189
}
185190
}

0 commit comments

Comments
 (0)