package org.testng.remote.strprotocol;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import org.testng.TestNGException;
/**
* String based socket based communication.
*
* @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
*/
public class StringMessageSenderHelper {
private boolean m_debugMode = false;
private Socket m_clientSocket;
private String m_host;
private int m_port;
/** Outgoing message stream. */
private PrintWriter m_outStream;
/** Ingoing message stream. */
private volatile BufferedReader m_inStream;
private ReaderThread m_readerThread;
private Object lock = new Object();
public StringMessageSenderHelper(final String host, final int port) {
m_host = host;
m_port = port;
}
/**
* Starts the connection.
*
* @return <TT>true</TT> if the connection was successfull, <TT>false</TT> otherwise
* @throws TestNGException if an exception occured while establishing the connection
*/
public boolean connect() {
if(m_debugMode) {
ppp("trying to connect " + m_host + ":" + m_port); //$NON-NLS-1$ //$NON-NLS-2$
}
Exception exception = null;
for(int i = 1; i < 20; i++) {
try {
m_clientSocket = new Socket(m_host, m_port);
try {
m_outStream = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_clientSocket.getOutputStream(), "UTF-8")), //$NON-NLS-1$
false /*autoflush*/);
}
catch(UnsupportedEncodingException ueex) {
// Should never happen
m_outStream = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(m_clientSocket.getOutputStream())),
false /*autoflush*/);
}
try {
m_inStream = new BufferedReader(new InputStreamReader(m_clientSocket.getInputStream(), "UTF-8")); //$NON-NLS-1$
}
catch(UnsupportedEncodingException ueex) {
// Should never happen
m_inStream = new BufferedReader(new InputStreamReader(m_clientSocket.getInputStream()));
}
m_readerThread = new ReaderThread();
m_readerThread.start();
return true;
}
catch(IOException ioe) {
exception = ioe;
}
try {
Thread.sleep(2000);
}
catch(InterruptedException e) {
;
}
}
throw new TestNGException("Cannot establish connection: " + m_host + ":" + m_port, exception);
}
/**
* Shutsdown the connection to the remote test listener.
*/
public void shutDown() {
if(null != m_outStream) {
m_outStream.close();
m_outStream = null;
}
try {
if(null != m_readerThread) {
m_readerThread.interrupt();
}
if(null != m_inStream) {
m_inStream.close();
m_inStream = null;
}
}
catch(IOException e) {
e.printStackTrace();
}
try {
if(null != m_clientSocket) {
m_clientSocket.close();
m_clientSocket = null;
}
}
catch(IOException e) {
if(m_debugMode) {
e.printStackTrace();
}
}
}
public void sendMessage(IMessage message) {
throw new UnsupportedOperationException("This operation is too generic yet.");
}
public void sendMessage(IStringMessage message) {
sendMessage(message.getMessageAsString());
}
private void sendMessage(String msg) {
if(null == m_outStream) {
ppp("WARNING the outputstream is null. Cannot send message.");
return;
}
if(m_debugMode) {
ppp(msg);
StringBuffer buf = new StringBuffer();
for(int i = 0; i < msg.length(); i++) {
if('\u0001' == msg.charAt(i)) {
ppp("word:[" + buf.toString() + "]");
buf.delete(0, buf.length());
}
else {
buf.append(msg.charAt(i));
}
}
ppp("word:[" + buf.toString() + "]");
}
synchronized(lock) {
m_outStream.println(msg);
m_outStream.flush();
try {
lock.wait();
}
catch(InterruptedException e) { }
}
}
private static void ppp(String msg) {
// System.out.println("[StringMessageSenderHelper]: " + msg); //$NON-NLS-1$
}
/**
* Reader thread that processes messages from the client.
*/
private class ReaderThread extends Thread {
public ReaderThread() {
super("ReaderThread"); //$NON-NLS-1$
}
@Override
public void run() {
try {
String message;
while((m_inStream != null) && (message = m_inStream.readLine()) != null) {
if(m_debugMode) {
ppp("Reply:" + message); //$NON-NLS-1$
}
boolean acknowledge = MessageHelper.ACK_MSG.equals(message);
boolean stop = MessageHelper.STOP_MSG.equals(message);
if(acknowledge || stop) {
synchronized(lock) {
lock.notifyAll();
}
if (stop) {
break;
}
}
}
}
catch(IOException ioe) {
;
}
}
}
}