package org.intrace.agent.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.intrace.agent.ClassTransformer;
import org.intrace.output.AgentHelper;
import org.intrace.output.InstruRunnable;
import org.intrace.shared.AgentConfigConstants;
import org.intrace.shared.TraceConfigConstants;
/**
* Server thread handling a single connected client.
*/
public class AgentClientConnection extends InstruRunnable
{
private final Socket connectedClient;
private final ClassTransformer transformer;
public ClassTransformer getTransformer() {
return transformer;
}
private boolean traceConnEstablished = false;
private final Object traceConnLock = new Object();
/**
* cTor
*
* @param agentServer
* @param xiConnectedClient
* @param xiTransformer
*/
public AgentClientConnection(Socket xiConnectedClient,
ClassTransformer xiTransformer)
{
super();
connectedClient = xiConnectedClient;
transformer = xiTransformer;
// System.out.println("## Control Connection Established (Port: " +
// xiConnectedClient.getPort() + ")");
}
public boolean isTraceConnEstablished()
{
return traceConnEstablished;
}
public void setTraceConnEstablished(boolean traceConnEstablished)
{
synchronized (traceConnLock)
{
this.traceConnEstablished = traceConnEstablished;
traceConnLock.notifyAll();
}
}
public void waitForTraceConn() throws InterruptedException
{
synchronized (traceConnLock)
{
while (!traceConnEstablished)
{
traceConnLock.wait();
}
}
}
/**
* Main client loop
* <ul>
* <li>Receive a message and send a response.
* </ul>
* Special Messages:
* <ul>
* <li>getsettings - Return a complete configuration Map
* <li>help - Return a Set of all the supported commands
* </ul>
*/
public void runMethod()
{
try
{
try
{
while (true)
{
String message = receiveMessage();
if (message.equals("getsettings"))
{
Map<String, String> settingsMap = new HashMap<String, String>();
settingsMap.putAll(transformer.getSettings());
settingsMap.putAll(AgentHelper.getSettings());
AgentServer.broadcastMessage(this, settingsMap);
}
else if (message.equals("help"))
{
Set<String> commandSet = new HashSet<String>();
commandSet.addAll(AgentConfigConstants.COMMANDS);
commandSet.addAll(TraceConfigConstants.COMMANDS);
sendMessage(commandSet);
}
else if (message.equalsIgnoreCase(AgentConfigConstants.START_ACTIVATE))
{
transformer.getResponse(this, message);
AgentServer.setStartSignalled();
}
else
{
List<String> responses = transformer.getResponse(this, message);
if (responses.size() > 0)
{
for (String response : responses)
{
sendMessage(response);
}
}
else
{
sendMessage("OK");
}
}
}
}
catch (IOException ex)
{
// System.out.println("## Control Connection Disconnected (Port: " +
// connectedClient.getPort() + ")");
}
connectedClient.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
finally
{
AgentServer.removeClientConnection(this);
}
}
/**
* Synchronously receive a String message.
*
* @return
* @throws IOException
*/
private String receiveMessage() throws IOException
{
InputStream in = connectedClient.getInputStream();
ObjectInputStream objIn = new ObjectInputStream(in);
try
{
String lRet = (String) objIn.readObject();
return lRet;
}
catch (ClassNotFoundException e)
{
throw new IOException(e);
}
}
/**
* Synchronously send an Object message.
*
* @param xiObject
* @throws IOException
*/
public void sendMessage(Object xiObject) throws IOException
{
synchronized (connectedClient)
{
// System.out.println("Agent send message: " + xiObject);
OutputStream out = connectedClient.getOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(xiObject);
objOut.flush();
}
}
/**
* Start the Client connection - create a new, named, daemon thread.
*/
public void start(int clientNum)
{
Thread clientThread = new Thread(this);
clientThread.setDaemon(true);
clientThread.setName("AgentServer-Client" + clientNum);
clientThread.start();
}
}