/**
* Sessions are created by agents in response to connection requests.
* Sessions manage conversations between agents. Each session interprets
* messages using a Responder.
*
* This class is usually subclassed to produce Responders that have
* specific functions.
*/
package com.jaivox.agent;
import java.io.*;
import java.net.*;
import com.jaivox.interpreter.InterServer;
public class Session extends Thread implements Runnable {
protected String sid;
protected Server server;
protected Socket socket;
protected Responder responder;
public static final int defaultWait = 100; // milliseconds
public static final int maxWaits = 10; // checking for In.ready
protected int waitTime;
protected BufferedReader in;
protected PrintWriter out;
public String outbuffer;
public static String
terminateMessage = "JviaTerminate",
invalidMessage = "JviaInvalid",
responseMessage = "JviaResponse",
finishedMessage = "JviaFinished";
/**
* Create a session with the specific details
@param s id of the session
@param serve server that owns this session
@param sock socket for communicating with this session
@param r responder associated with this session
*/
public Session (String s, Server serve, Socket sock, Responder r) {
sid = s;
server = serve;
socket = sock;
responder = r;
r.owner = this;
waitTime = defaultWait; // can modify if needed
try {
start ();
}
catch (Exception e) {
Debug ("Session " + e.toString ());
}
}
public Session () {
}
void Debug (String message) {
System.out.println ("[Session]"+sid+":"+message);
}
/**
* The session stays in its run method. It handles each request
* that is received within this method and creates responses to
* those requests. Some requests, such as those asking to terminate
* the session are handled within the run () method.
*/
public void run () {
try {
in = new BufferedReader (new InputStreamReader (
socket.getInputStream ()));
out = new PrintWriter (socket.getOutputStream ());
while (true) {
if (outbuffer != null) {
out.println (outbuffer);
out.flush ();
sleep (waitTime);
Debug ("sent:" + outbuffer);
outbuffer = null;
}
String line = readLineFromSocket ();
if (line == null) continue;
Debug ("read "+line);
MessageData response = responder.respond (line);
String result = response.getValue ("action");
if (result.equals (terminateMessage)) {
break;
}
else if (result.equals (invalidMessage)) {
Debug ("Invalid message: "+line);
continue;
}
else if (result.equals (responseMessage)) {
outbuffer = response.createMessage ();
Debug ("replying: " + outbuffer);
}
else if (result.equals (finishedMessage)) {
Debug ("Response received, no further action required");
continue;
}
else {
Debug ("Unhandled message:"+line);
continue;
}
}
Debug ("Closing session "+sid);
terminate ();
socket.close ();
server.removeSession (this);
interrupt ();
Debug (sid+" interrupted.");
}
catch (Exception e) {
Debug (sid+":run "+e.toString ());
e.printStackTrace ();
}
}
protected String readLineFromSocket () {
// wait for a while
try {
for (int i=0; i < maxWaits && !(in.ready ()); i++)
sleep (waitTime);
if (in.ready ()) {
StringBuffer sb = new StringBuffer ();
while(true) {
if (in.ready ()) {
char ch = (char)in.read ();
if(ch == '\n')
break;
sb.append (ch);
}
else break;
}
String msg = new String (sb);
msg = msg.trim ();
if (msg.length() > 1)
return msg;
else {
/*
String dstring = new String ("Bytes ");
for (int i=0; i<msg.length(); i++) {
int j = (int)(msg.charAt(i));
dstring+= (" "+j);
}
Debug (dstring);
*/
return null;
}
}
else
return null;
}
catch (Exception e) {
Debug ("readLineFromSocket: " + e.toString ());
return null;
}
}
public void terminate () {
try {
socket.close ();
server.removeSession (this);
Debug ("terminated");
}
catch (Exception e) {
Debug (sid+":terminate "+e.toString ());
}
}
public String getSid () {
return sid;
}
public void setSid (String id) {
this.sid = id;
}
public Server getServer () {
return server;
}
public void setServer (Server server) {
this.server = server;
}
public String getServerId () {
InterServer server = (InterServer)getServer ();
String serverId = server.getServerId ();
return serverId;
}
public Socket getSocket () {
return socket;
}
public void setSocket (Socket socket) {
this.socket = socket;
}
public Responder getResponder () {
return responder;
}
public void setResponder (Responder responder) {
this.responder = responder;
}
public int getWaitTime () {
return waitTime;
}
public void setWaitTime (int waitTime) {
this.waitTime = waitTime;
}
public static int getDefaultWait () {
return defaultWait;
}
}