10
10
*
11
11
* SPDX-License-Identifier: EPL-2.0
12
12
*/
13
- package org .openhab .binding .xmppclient .internal ;
13
+ package org .openhab .binding .xmppclient .internal . client ;
14
14
15
15
import java .io .File ;
16
16
import java .io .IOException ;
17
17
import java .net .URL ;
18
18
import java .util .HashSet ;
19
+ import java .util .Objects ;
19
20
import java .util .Set ;
20
21
22
+ import org .eclipse .jdt .annotation .NonNullByDefault ;
23
+ import org .eclipse .jdt .annotation .Nullable ;
21
24
import org .jivesoftware .smack .AbstractXMPPConnection ;
25
+ import org .jivesoftware .smack .ConnectionConfiguration .SecurityMode ;
22
26
import org .jivesoftware .smack .ConnectionListener ;
23
27
import org .jivesoftware .smack .ReconnectionManager ;
24
28
import org .jivesoftware .smack .SmackException ;
44
48
* The {@link XMPPClient} is lib for handling XMPP connection and messaging
45
49
*
46
50
* @author Pavel Gololobov - Initial contribution
51
+ * @author Leo Siepel - Add reconnection logic
47
52
*/
53
+ @ NonNullByDefault
48
54
public class XMPPClient implements IncomingChatMessageListener , ConnectionListener {
49
55
private final Logger logger = LoggerFactory .getLogger (XMPPClient .class );
50
- private AbstractXMPPConnection connection ;
51
- private ChatManager chatManager ;
52
- private HttpFileUploadManager httpFileUploadManager ;
56
+ private @ Nullable AbstractXMPPConnection connection ;
57
+ private @ Nullable ChatManager chatManager ;
58
+ private @ Nullable HttpFileUploadManager httpFileUploadManager ;
53
59
private Set <XMPPClientMessageSubscriber > subscribers = new HashSet <>();
60
+ private final XMPPClientEventlistener eventListener ;
61
+
62
+ public XMPPClient (XMPPClientEventlistener eventListener ) {
63
+ this .eventListener = eventListener ;
64
+ }
54
65
55
66
public void subscribe (XMPPClientMessageSubscriber channel ) {
56
67
logger .debug ("Channel {} subscribed" , channel .getName ());
@@ -62,62 +73,75 @@ public void unsubscribe(XMPPClientMessageSubscriber channel) {
62
73
subscribers .remove (channel );
63
74
}
64
75
65
- public void connect (String host , Integer port , String login , String domain , String password )
66
- throws XMPPException , SmackException , IOException {
76
+ public void connect (String host , Integer port , String login , String domain , String password ,
77
+ SecurityMode securityMode ) throws XMPPClientConfigException , XMPPClientException {
67
78
disconnect ();
68
79
String serverHost = domain ;
69
- if (( host != null ) && ! host .isEmpty ()) {
80
+ if (! host .isBlank ()) {
70
81
serverHost = host ;
71
82
}
72
83
73
- XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration .builder () //
74
- .setHost (serverHost ) //
75
- .setPort (port ) //
76
- .setUsernameAndPassword (login , password ) //
77
- .setXmppDomain (domain ) //
78
- .build ();
84
+ XMPPTCPConnectionConfiguration config ;
85
+ try {
86
+ config = XMPPTCPConnectionConfiguration .builder () //
87
+ .setHost (serverHost ) //
88
+ .setPort (port ) //
89
+ .setUsernameAndPassword (login , password ) //
90
+ .setXmppDomain (domain ) //
91
+ .setSecurityMode (securityMode )//
92
+ .build ();
93
+ } catch (XmppStringprepException e ) {
94
+ throw new XMPPClientConfigException (Objects .requireNonNullElse (e .getMessage (), "Unknown error message" ));
95
+ }
79
96
80
- connection = new XMPPTCPConnection (config );
81
- connection .addConnectionListener (this );
97
+ AbstractXMPPConnection connectionLocal = new XMPPTCPConnection (config );
98
+ connection = connectionLocal ;
99
+ connectionLocal .addConnectionListener (this );
82
100
83
- ReconnectionManager reconnectionManager = ReconnectionManager .getInstanceFor (connection );
101
+ ReconnectionManager reconnectionManager = ReconnectionManager .getInstanceFor (connectionLocal );
84
102
reconnectionManager .enableAutomaticReconnection ();
85
103
86
104
Identity identity = new Identity ("client" , "openHAB" , "bot" );
87
105
ServiceDiscoveryManager sdm = ServiceDiscoveryManager .getInstanceFor (connection );
88
106
sdm .setIdentity (identity );
89
107
90
108
try {
91
- connection .connect ().login ();
92
- } catch (InterruptedException ex ) {
109
+ connectionLocal .connect ().login ();
110
+ } catch (InterruptedException | XMPPException | SmackException | IOException e ) {
111
+ throw new XMPPClientException (Objects .requireNonNullElse (e .getMessage (), "Unknown error message" ),
112
+ e .getCause ());
93
113
}
94
114
95
- chatManager = ChatManager .getInstanceFor (connection );
115
+ ChatManager chatManager = ChatManager .getInstanceFor (connection );
96
116
chatManager .addIncomingListener (this );
117
+ this .chatManager = chatManager ;
97
118
httpFileUploadManager = HttpFileUploadManager .getInstanceFor (connection );
98
119
}
99
120
100
121
public void disconnect () {
122
+ AbstractXMPPConnection connection = this .connection ;
101
123
if (connection != null ) {
102
124
connection .disconnect ();
103
125
}
104
126
}
105
127
106
128
public void sendMessage (String to , String message ) {
107
129
if (connection == null ) {
108
- logger . warn ("XMPP connection is null" );
130
+ eventListener . onErrorEvent ("XMPP connection is null" );
109
131
return ;
110
132
}
133
+
134
+ ChatManager chatManager = this .chatManager ;
111
135
if (chatManager == null ) {
112
- logger . warn ("XMPP chatManager is null" );
136
+ eventListener . onErrorEvent ("XMPP chatManager is null" );
113
137
return ;
114
138
}
115
139
try {
116
140
EntityBareJid jid = JidCreate .entityBareFrom (to );
117
141
Chat chat = chatManager .chatWith (jid );
118
142
chat .send (message );
119
143
} catch (XmppStringprepException | SmackException .NotConnectedException | InterruptedException e ) {
120
- logger .info ("XMPP message sending error" , e );
144
+ logger .warn ("XMPP message sending error" , e );
121
145
}
122
146
}
123
147
@@ -126,12 +150,13 @@ public void sendImageByHTTP(String to, String filename) {
126
150
logger .warn ("XMPP connection is null" );
127
151
return ;
128
152
}
129
- if (httpFileUploadManager == null ) {
153
+ HttpFileUploadManager httpFileUploadManagerLocal = httpFileUploadManager ;
154
+ if (httpFileUploadManagerLocal == null ) {
130
155
logger .warn ("XMPP httpFileUploadManager is null" );
131
156
return ;
132
157
}
133
158
try {
134
- URL u = httpFileUploadManager .uploadFile (new File (filename ));
159
+ URL u = httpFileUploadManagerLocal .uploadFile (new File (filename ));
135
160
// Use Stanza oob
136
161
this .sendMessage (to , u .toString ());
137
162
} catch (XMPPException .XMPPErrorException | SmackException | InterruptedException | IOException e ) {
@@ -140,7 +165,12 @@ public void sendImageByHTTP(String to, String filename) {
140
165
}
141
166
142
167
@ Override
143
- public void newIncomingMessage (EntityBareJid from , Message message , Chat chat ) {
168
+ public void newIncomingMessage (@ Nullable EntityBareJid from , @ Nullable Message message , @ Nullable Chat chat ) {
169
+ if (from == null || message == null || chat == null ) {
170
+ logger .debug ("newIncomingMessage with atleast one null argument, should not happen" );
171
+ return ;
172
+ }
173
+
144
174
logger .debug ("XMPP {} says {}" , from .asBareJid ().toString (), message .getBody ());
145
175
for (XMPPClientMessageSubscriber subscriber : subscribers ) {
146
176
logger .debug ("Push to subscriber {}" , subscriber .getName ());
@@ -149,30 +179,26 @@ public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
149
179
}
150
180
151
181
@ Override
152
- public void connected (XMPPConnection connection ) {
182
+ public void connected (@ Nullable XMPPConnection connection ) {
153
183
logger .debug ("Connected to XMPP server." );
184
+ eventListener .onAllOk ();
154
185
}
155
186
156
187
@ Override
157
- public void authenticated (XMPPConnection connection , boolean resumed ) {
188
+ public void authenticated (@ Nullable XMPPConnection connection , boolean resumed ) {
158
189
logger .debug ("Authenticated to XMPP server." );
190
+ eventListener .onAllOk ();
159
191
}
160
192
161
193
@ Override
162
194
public void connectionClosed () {
163
195
logger .debug ("XMPP connection was closed." );
196
+ eventListener .onErrorEvent ("XMPP connection was closed." );
164
197
}
165
198
166
199
@ Override
167
- public void connectionClosedOnError (Exception e ) {
200
+ public void connectionClosedOnError (@ Nullable Exception e ) {
168
201
logger .debug ("Connection to XMPP server was lost." );
169
- if (connection != null ) {
170
- connection .disconnect ();
171
- try {
172
- connection .connect ().login ();
173
- } catch (SmackException | IOException | XMPPException | InterruptedException ex ) {
174
- logger .info ("XMPP connection error" , ex );
175
- }
176
- }
202
+ eventListener .onErrorEvent ("XMPP connection was closed." );
177
203
}
178
204
}
0 commit comments