/*******************************************************************************
* Copyright (c) 2004, 2011 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.app.autrun;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jubula.app.autrun.i18n.Messages;
import org.eclipse.jubula.autagent.commands.IStartAut;
import org.eclipse.jubula.communication.internal.connection.ConnectionState;
import org.eclipse.jubula.communication.internal.connection.RestartAutProtocol;
import org.eclipse.jubula.tools.internal.constants.AutConfigConstants;
import org.eclipse.jubula.tools.internal.registration.AutIdentifier;
import org.eclipse.jubula.tools.internal.utils.IsAliveThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author BREDEX GmbH
* @created Sept 07, 2011
*/
public class AutRunner {
/**
* @author BREDEX GmbH
*/
private final class AgentConnectionWatcher extends Thread {
/** the writer */
private final PrintWriter m_writer;
/** the socket */
private final Socket m_agentSocket;
/** the buffered reader */
private final BufferedReader m_reader;
/**
* @param name
* the name
* @param writer
* the writer
* @param agentSocket
* the agent socket
* @param reader
* the reader
*/
private AgentConnectionWatcher(String name, PrintWriter writer,
Socket agentSocket, BufferedReader reader) {
super(name);
m_writer = writer;
m_agentSocket = agentSocket;
m_reader = reader;
}
/** {@inheritDoc} */
public void run() {
try {
String line = m_reader.readLine();
if (line != null) {
if (line.equals(
RestartAutProtocol.REQ_PREPARE_FOR_RESTART)) {
// make sure that we have a keep alive thread running so
// the JVM won't shut down during AUT restart
Thread restartThread = new IsAliveThread() {
public void run() {
m_writer.println(RESPONSE_OK);
try {
String restartReq = m_reader.readLine();
if (RestartAutProtocol.REQ_RESTART
.equals(restartReq)) {
AutRunner.this.run();
}
} catch (IOException e) {
LOG.error(Messages.restartAutFailed, e);
} finally {
try {
m_agentSocket.close();
} catch (IOException e) {
// Error while closing socket. Ignore.
}
}
}
};
restartThread.setDaemon(false);
restartThread.start();
}
}
} catch (IOException e) {
LOG.error(Messages.restartAutFailed, e);
}
}
}
/** response OK when thread was started */
private static final String RESPONSE_OK = "Response.OK"; //$NON-NLS-1$
/** the thread name */
private static final String AGENT_CONNECTION_THREAD_NAME = "AUT Agent Connection"; //$NON-NLS-1$
/** the logger */
private static final Logger LOG =
LoggerFactory.getLogger(AutRunner.class);
/** settings used to start the AUT */
private Map<String, String> m_autConfiguration;
/** the object responsible for actually starting the AUT */
private IStartAut m_startAut;
/** the address for the AUT Agent */
private InetSocketAddress m_agentAddr;
/**
* Constructor
*
* @param autToolkit Toolkit for the AUT managed by this instance.
* @param autIdentifier Identifier for the AUT managed by this instance.
* @param agentAddr Address of the AUT-Agent with which the AUT should be
* registered.
* @param autConfiguration Properties required for starting the AUT.
*
* @throws ClassNotFoundException If no class can be found for starting an
* AUT for the given toolkit.
* @throws InstantiationException
* @throws IllegalAccessException
*/
public AutRunner(String autToolkit, AutIdentifier autIdentifier,
InetSocketAddress agentAddr, Map<String, String> autConfiguration)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException {
String className = "org.eclipse.jubula.autagent.commands.Start" //$NON-NLS-1$
+ autToolkit + "AutServerCommand"; //$NON-NLS-1$
Class< ? > autServerClass = Class.forName(className);
m_agentAddr = agentAddr;
m_autConfiguration = new HashMap<String, String>(autConfiguration);
m_autConfiguration.put(AutConfigConstants.AUT_AGENT_HOST,
agentAddr.getHostName());
m_autConfiguration.put(AutConfigConstants.AUT_AGENT_PORT,
String.valueOf(agentAddr.getPort()));
m_autConfiguration.put(AutConfigConstants.AUT_NAME,
autIdentifier.getExecutableName());
m_startAut = (IStartAut)autServerClass.newInstance();
}
/**
* Starts the AUT managed by the receiver.
*
* @throws ConnectException If unable to connect to the AUT Agent (if,
* for example, there is no AUT Agent running on the given
* hostname / port)
* @throws IOException if an I/O error occurs during AUT startup.
*/
public void run() throws IOException, ConnectException {
// Establish connection to AUT Agent
if (m_agentAddr.getAddress() == null) {
LOG.error(Messages.errorAutAgentHost);
throw new ConnectException(Messages.errorAutAgentHost);
}
final Socket agentSocket =
new Socket(m_agentAddr.getAddress(), m_agentAddr.getPort());
final PrintWriter writer = new PrintWriter(
agentSocket.getOutputStream(), true);
final BufferedReader reader = new BufferedReader(
new InputStreamReader(agentSocket.getInputStream()));
// wait for the "Client Type Request" message
reader.readLine();
writer.println(ConnectionState.CLIENT_TYPE_AUTRUN);
writer.println(
m_autConfiguration.get(AutConfigConstants.AUT_NAME));
writer.println(m_startAut.getClass().getName());
Thread agentConnectionThread = new AgentConnectionWatcher(
AGENT_CONNECTION_THREAD_NAME, writer, agentSocket, reader);
agentConnectionThread.setDaemon(true);
agentConnectionThread.start();
m_startAut.startAut(m_autConfiguration);
}
}