blob: c53148665a35e108712fbeece16ffeb73bc9324f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Julien Ruaux: jruaux@octo.com
* Vincent Massol: vmassol@octo.com
*
* Adapted by:
* Alexandru Popescu: the_mindstorm@evolva.ro
******************************************************************************/
package org.testng.remote.strprotocol;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
/**
* The client side of the RemoteTestRunner. Handles the
* marshaling of the different messages.
*/
public abstract class AbstractRemoteTestRunnerClient {
/**
* An array of listeners that are informed about test events.
*/
protected IRemoteSuiteListener[] m_suiteListeners;
protected IRemoteTestListener[] m_testListeners;
/**
* The server socket
*/
private ServerSocket fServerSocket;
private Socket fSocket;
private PrintWriter m_outputWriter;
private BufferedReader m_inputReader;
/**
* Start listening to a test run. Start a server connection that
* the RemoteTestRunner can connect to.
*/
public synchronized void startListening(IRemoteSuiteListener[] suiteListeners,
IRemoteTestListener[] testListeners,
ServerConnection serverConnection) {
m_suiteListeners= suiteListeners;
m_testListeners= testListeners;
serverConnection.start();
}
public IRemoteSuiteListener[] getSuiteListeners() {
return m_suiteListeners;
}
public IRemoteTestListener[] getTestListeners() {
return m_testListeners;
}
private synchronized void shutdown() {
if(m_outputWriter != null) {
m_outputWriter.close();
m_outputWriter = null;
}
try {
if(m_inputReader != null) {
m_inputReader.close();
m_inputReader = null;
}
}
catch(IOException e) {
e.printStackTrace();
}
try {
if(fSocket != null) {
fSocket.close();
fSocket = null;
}
}
catch(IOException e) {
e.printStackTrace();
}
try {
if(fServerSocket != null) {
fServerSocket.close();
fServerSocket = null;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
public boolean isRunning() {
return fSocket != null;
}
/**
* Requests to stop the remote test run.
*/
public synchronized void stopTest() {
if(isRunning()) {
if(null != m_outputWriter) {
m_outputWriter.println(MessageHelper.STOP_MSG);
m_outputWriter.flush();
}
shutdown();
}
}
private String readMessage(BufferedReader in) throws IOException {
return in.readLine();
}
private void receiveMessage(String message) {
int messageType = MessageHelper.getMessageType(message);
try {
if(messageType < MessageHelper.SUITE) {
// Generic message
GenericMessage gm = MessageHelper.unmarshallGenericMessage(message);
notifyStart(gm);
}
else if(messageType < MessageHelper.TEST) {
// Suite message
SuiteMessage sm = MessageHelper.createSuiteMessage(message);
notifySuiteEvents(sm);
}
else if(messageType < MessageHelper.TEST_RESULT) {
// Test message
TestMessage tm = MessageHelper.createTestMessage(message);
notifyTestEvents(tm);
}
else {
// TestResult message
TestResultMessage trm = MessageHelper.unmarshallTestResultMessage(message);
notifyResultEvents(trm);
}
}
finally {
if(isRunning() && (null != m_outputWriter)) {
m_outputWriter.println(MessageHelper.ACK_MSG);
m_outputWriter.flush();
}
}
}
protected abstract void notifyStart(final GenericMessage genericMessage);
protected abstract void notifySuiteEvents(final SuiteMessage suiteMessage);
protected abstract void notifyTestEvents(final TestMessage testMessage);
protected abstract void notifyResultEvents(final TestResultMessage testResultMessage);
/**
* Reads the message stream from the RemoteTestRunner
*/
public abstract class ServerConnection extends Thread {
int fServerPort;
public ServerConnection(int port) {
super("ServerConnection"); //$NON-NLS-1$
fServerPort = port;
}
@Override
public void run() {
try {
fServerSocket = new ServerSocket(fServerPort);
fSocket = fServerSocket.accept();
try {
m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream(),
"UTF-8")); //$NON-NLS-1$
}
catch(UnsupportedEncodingException e) {
m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream()));
}
try {
m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"),
true); //$NON-NLS-1$
}
catch(UnsupportedEncodingException e1) {
m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true);
}
String message;
while((m_inputReader != null) && ((message = readMessage(m_inputReader)) != null)) {
receiveMessage(message);
}
}
catch(SocketException e) {
handleThrowable(e);
}
catch(IOException e) {
handleThrowable(e);
}
finally {
shutdown();
}
}
protected abstract void handleThrowable(Throwable cause);
}
}