package gis2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import rescuecore2.Constants;
import rescuecore2.config.Config;
import rescuecore2.misc.CommandLineOptions;
import rescuecore2.misc.java.LoadableTypeProcessor;
import rescuecore2.log.Logger;
import rescuecore2.worldmodel.WorldModel;
import rescuecore2.worldmodel.Entity;
import rescuecore2.connection.Connection;
import rescuecore2.connection.TCPConnection;
import rescuecore2.connection.ConnectionListener;
import rescuecore2.connection.ConnectionException;
import rescuecore2.registry.Registry;
import rescuecore2.messages.Message;
import rescuecore2.messages.control.KGConnect;
import rescuecore2.messages.control.GKConnectOK;
import rescuecore2.messages.control.Shutdown;
/**
* This class is used for starting a remote GIS server.
*/
public final class GISServer {
private static final long WAIT_TIME = 1000;
private ServerSocket server;
private WorldModel<? extends Entity> world;
private volatile boolean running;
private GISServer(int port, WorldModel<? extends Entity> world) throws IOException {
server = new ServerSocket(port);
this.world = world;
running = true;
}
/**
Start the GIS server.
@param args Command line arguments: <-c config file>
*/
public static void main(String[] args) {
Config config = new Config();
try {
CommandLineOptions.processArgs(args, config);
int port = config.getIntValue(Constants.GIS_PORT_NUMBER_KEY, Constants.DEFAULT_GIS_PORT_NUMBER);
processJarFiles(config);
GMLWorldModelCreator creator = new GMLWorldModelCreator();
new GISServer(port, creator.buildWorldModel(config)).run();
Logger.info("GIS server listening on port " + port);
}
// CHECKSTYLE:OFF:IllegalCatch
catch (Exception e) {
Logger.fatal("Error starting GIS server", e);
}
// CHECKSTYLE:ON:IllegalCatch
}
private static void processJarFiles(Config config) throws IOException {
LoadableTypeProcessor processor = new LoadableTypeProcessor(config);
processor.addFactoryRegisterCallbacks(Registry.SYSTEM_REGISTRY);
processor.process();
}
/**
Run the GIS server.
*/
public void run() {
while (running) {
try {
Socket socket = server.accept();
new ServerThread(socket).start();
}
catch (IOException e) {
Logger.error("Error accepting connection", e);
running = false;
}
}
}
private class ServerThread extends Thread implements ConnectionListener {
private Socket socket;
private boolean dead;
public ServerThread(Socket socket) {
this.socket = socket;
dead = false;
}
@Override
public void run() {
TCPConnection c = null;
try {
c = new TCPConnection(socket);
}
catch (IOException e) {
Logger.error("Error starting TCPConnection", e);
return;
}
c.startup();
c.addConnectionListener(this);
synchronized (this) {
while (!dead) {
try {
this.wait(WAIT_TIME);
}
catch (InterruptedException e) {
dead = true;
}
}
}
c.shutdown();
}
@Override
public void messageReceived(Connection c, Message msg) {
if (msg instanceof KGConnect) {
// Send a GKConnectOK
try {
c.sendMessage(new GKConnectOK(world.getAllEntities()));
}
catch (ConnectionException e) {
Logger.fatal("Error sending message", e);
die();
}
}
if (msg instanceof Shutdown) {
die();
}
}
private void die() {
synchronized (this) {
dead = true;
notifyAll();
}
running = false;
}
}
}