/*--
* #%L
* Cognifide Actions
* %%
* Copyright (C) 2015 Cognifide
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package com.cognifide.actions.msg.websocket.client;
import com.cognifide.actions.msg.websocket.api.SocketReceiver;
import com.cognifide.actions.msg.websocket.servlet.MessageWebsocketServlet;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;
import javax.websocket.DeploymentException;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import org.apache.commons.lang.StringUtils;
import org.glassfish.tyrus.client.ClientManager;
import org.glassfish.tyrus.client.ClientProperties;
import org.glassfish.tyrus.client.auth.Credentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SocketClientRunnable extends Endpoint implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(SocketClientRunnable.class);
private final Set<SocketReceiver> receivers;
private final String serverUrl;
private final ClientManager client;
private Session session;
private volatile boolean shouldStop = false;
public SocketClientRunnable(Set<SocketReceiver> receivers, String serverUrl, String username,
String password) throws URISyntaxException {
this.receivers = receivers;
this.serverUrl = serverUrl.replace("http://", "ws://") + MessageWebsocketServlet.PATH;
client = ClientManager.createClient();
String clientUsername = StringUtils.defaultIfEmpty(username, "admin");
String clientPassword = StringUtils.defaultIfEmpty(password, "admin");
client.getProperties()
.put(ClientProperties.CREDENTIALS, new Credentials(clientUsername, clientPassword));
}
@Override
public void onOpen(final Session session, EndpointConfig endpointConfig) {
LOG.info("Session {} opened", session.getId());
this.session = session;
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
LOG.debug("Got message: " + message);
gotMessage(message);
try {
session.getBasicRemote().sendText("OK");
} catch (IOException e) {
LOG.error("Can't respond to the message");
}
}
});
}
@Override
public void run() {
reconnect();
while (!shouldStop) {
if (connectionBroken()) {
String sessionId = session != null ? session.getId() : null;
LOG.debug("Connection was lost... session: {} no longer active", sessionId);
reconnect();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e1) {
LOG.error("Interrupted", e1);
return;
}
}
}
public void stop() {
shouldStop = true;
closeSession();
}
private boolean connectionBroken() {
return session == null || !session.isOpen();
}
private void reconnect() {
closeSession();
try {
LOG.debug("Connecting to server: `{}` (receivers no: {})", serverUrl, receivers.size());
final Session currentSession = client.connectToServer(this, new URI(serverUrl));
LOG.debug("New session created: ", currentSession.getId());
} catch (IOException | DeploymentException | URISyntaxException e) {
LOG.error("Can't connect to the server {}", serverUrl, e);
}
}
private void closeSession() {
String sessionId = session != null ? session.getId() : null;
LOG.info("Closing session: {}", sessionId);
if (session != null) {
try {
session.close();
} catch (IOException e) {
LOG.error("Can't close session", e);
}
}
}
protected void gotMessage(String message) {
for (SocketReceiver receiver : receivers) {
receiver.gotMessage(message);
}
}
}