package org.ch3ck3r.jgbx;
import java.io.InputStream;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.ch3ck3r.jgbx.callbacks.Callback;
import org.ch3ck3r.jgbx.error.JGBXException;
import org.ch3ck3r.jgbx.error.JGBXFault;
import org.ch3ck3r.jgbx.internal.JGBXFuture;
import org.ch3ck3r.jgbx.internal.JGBXParser;
import org.ch3ck3r.jgbx.responses.Response;
/**
* The JGBX response receiver thread
*
* @author Frank Zechert
* @version 1
*/
class ReceiverThread extends Thread {
/**
* The logger.
*/
private static final Logger logger = Logger.getLogger(ReceiverThread.class);
/**
* The polling timeout in milliseconds.
*/
private static final int POLLING_TIMEOUT = 100;
/**
* Indicates wether the thread should exit.
*/
private boolean shouldExit;
/**
* The JGBXConnector instance.
*/
private final JGBXConnector jgbxc;
/**
* The input stream to receive something from.
*/
private final InputStream inputStream;
/**
* The response queue to work on.
*/
private final ConcurrentHashMap<Integer, JGBXFuture<? extends Response>> responseQueue;
/**
* The xml parser.
*/
private final JGBXParser parser;
/**
* Create a new receiver thread.
*
* @param jgbxConnector
* The JGBXConnector.
* @param inputStream
* The input stream to receive data from.
* @param responseQueue
* The response queue to queue the responses.
*/
public ReceiverThread(final JGBXConnector jgbxConnector, final InputStream inputStream,
final ConcurrentHashMap<Integer, JGBXFuture<? extends Response>> responseQueue) {
super("JGBX Response Receiver Thread");
this.shouldExit = false;
this.jgbxc = jgbxConnector;
this.inputStream = inputStream;
this.responseQueue = responseQueue;
this.parser = new JGBXParser();
}
/**
* Exit this thread.
*/
public void exit() {
logger.debug("ReceiverThread was asked to exit.");
this.shouldExit = true;
}
/**
* Start polling the request queue and send the requests to the server.
*/
@Override
public void run() {
logger.info("ReceiverThread is running");
while (!this.shouldExit && this.jgbxc.isConnected()) {
try {
final Integer length = this.jgbxc.getNextMessageLenght(POLLING_TIMEOUT);
if (length == -1 || this.shouldExit) {
continue;
}
final Integer handle = this.jgbxc.getNextMessageHandle();
final String message = this.jgbxc.getNextMessage(length);
if (handle < 0) {
// received response
logger.debug("Received message: [" + length + "] [" + handle + "] " + message);
final JGBXFuture<? extends Response> response = this.responseQueue.get(handle);
if (response == null) {
logger.warn("Received message with handle [" + handle
+ "] which was not requested and is no callback.");
continue;
}
this.responseQueue.remove(handle);
try {
final Response responseData = this.parser.responseFromXML(message, response.getResponseClass());
logger.debug(responseData);
response.putResponse(responseData);
}
catch (final JGBXException | JGBXFault e) {
response.fail(e);
}
}
else {
// received callback
logger.debug("Received callback: [" + length + "] [" + handle + "] " + message);
final Callback callbackData = this.parser.callbackFromXML(message);
logger.debug(callbackData);
}
}
catch (final Throwable e) {
if (!this.shouldExit) {
logger.error(e);
this.jgbxc.disconnect();
break;
}
}
}
logger.info("ReceiverThread is exited");
}
}