/*******************************************************************************
* Copyright (c) 2014 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.client.internal;
import java.util.Map;
import org.eclipse.jubula.client.internal.exceptions.ConnectionException;
import org.eclipse.jubula.client.internal.impl.AUTAgentImpl.ErrorListener;
import org.eclipse.jubula.communication.internal.message.ConnectToAutMessage;
import org.eclipse.jubula.communication.internal.message.SendAUTListOfSupportedComponentsMessage;
import org.eclipse.jubula.tools.internal.constants.EnvConstants;
import org.eclipse.jubula.tools.internal.exception.CommunicationException;
import org.eclipse.jubula.tools.internal.exception.JBVersionException;
import org.eclipse.jubula.tools.internal.registration.AutIdentifier;
import org.eclipse.jubula.tools.internal.utils.TimeUtil;
import org.eclipse.jubula.tools.internal.xml.businessmodell.ComponentClass;
import org.eclipse.jubula.tools.internal.xml.businessprocess.ProfileBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class represents the connection to the AUTServer which controls the
* application under test.
*
* This class is implemented as a singleton. The server configuration contains
* detailed information, how this instance can be contacted.
*
* @author BREDEX GmbH
* @created 22.07.2004
*/
public class AUTConnection extends BaseAUTConnection {
/** the logger */
static final Logger LOGGER = LoggerFactory.getLogger(AUTConnection.class);
/** the singleton instance */
private static AUTConnection instance = null;
/**
* private constructor. creates a communicator
* @param port the port or 0 if automatically a port should be assigned
* @throws ConnectionException
* containing a detailed message why the connection could not
* initialized
*/
private AUTConnection(int port) throws ConnectionException {
super(port);
}
/**
* Method to get the single instance of this class.
*
* @throws ConnectionException
* if an error occurs during initialization.
* @return the instance of this Singleton
*/
public static synchronized AUTConnection getInstance()
throws ConnectionException {
if (instance == null) {
instance = new AUTConnection(0);
}
return instance;
}
/**
* Resets this singleton: Closes the communicator
* removes the listeners.<br>
* <b>Note: </b><br>
* This method is used by the Restart-AUT-Action only to avoid errors while
* reconnecting with the AUTServer.<br>
* This is necessary because the disconnect from the AUTServer is implemented
* badly which will be corrected in a future version!
*/
public synchronized void reset() {
super.reset();
instance = null;
}
/**
* @param autId AutIdentifier of AUT
* @param typeMapping
* @return <code>true</code> if a connection to the AUT could be
* established. Otherwise <code>false</code>.
*/
public boolean connectToAut(AutIdentifier autId,
Map<ComponentClass, String> typeMapping) {
return connectToAutImpl(autId, typeMapping, CONNECT_TO_AUT_TIMEOUT);
}
/**
* @param autId AutIdentifier of AUT
* @param typeMapping
* @param timeOut the time out value
* @return <code>true</code> if a connection to the AUT could be
* established. Otherwise <code>false</code>.
*/
public boolean connectToAut(AutIdentifier autId,
Map<ComponentClass, String> typeMapping, int timeOut) {
return timeOut <= 0 ? connectToAut(autId, typeMapping)
: connectToAutImpl(autId, typeMapping, timeOut);
}
/**
* Establishes a connection to the Running AUT with the given ID.
*
* @param autId
* The ID of the Running AUT to connect to.
* @param typeMapping
* the type mapping to use
* @param timeOut until this time wait for connecting to the AUT
* @return <code>true</code> if a connection to the AUT could be
* established. Otherwise <code>false</code>.
*/
private boolean connectToAutImpl(AutIdentifier autId,
Map<ComponentClass, String> typeMapping, int timeOut) {
if (!isConnected()) {
try {
LOGGER.info("Establishing connection to AUT..."); //$NON-NLS-1$
run();
getCommunicator().addCommunicationErrorListener(
new ErrorListener(Thread.currentThread()));
final AutAgentConnection autAgent = AutAgentConnection
.getInstance();
autAgent.getCommunicator().send(
new ConnectToAutMessage(EnvConstants.LOCALHOST_FQDN,
getCommunicator().getLocalPort(), autId));
long startTime = System.currentTimeMillis();
while (!isConnected()
&& autAgent.isConnected()
&& startTime + timeOut > System
.currentTimeMillis()) {
TimeUtil.delay(200);
}
if (isConnected()) {
setConnectedAutId(autId);
LOGGER.info("Connection to AUT established."); //$NON-NLS-1$
setup(typeMapping);
return true;
}
LOGGER.error("Connection to AUT could not be established."); //$NON-NLS-1$
} catch (CommunicationException e) {
LOGGER.error("Error occurred while establishing connection to AUT.", e); //$NON-NLS-1$
} catch (JBVersionException e) {
LOGGER .error("Version error occurred while establishing connection to AUT.", e); //$NON-NLS-1$
}
} else {
LOGGER.warn("Cannot establish new connection to AUT: Connection to AUT already exists."); //$NON-NLS-1$
}
return false;
}
/**
* setup the connection between API and AUT
*
* @param technicalTypeMapping
* the technical type mapping to use
* @throws NotConnectedException
* if there is no connection to an AUT.
* @throws ConnectionException
* if no connection to an AUT could be initialized.
* @throws CommunicationException
* if an error occurs while communicating with the AUT.
*/
public void setup(Map<ComponentClass, String> technicalTypeMapping)
throws NotConnectedException, ConnectionException,
CommunicationException {
sendKeyboardLayoutToAut();
// FIXME MT: workaround for racing condition
TimeUtil.delay(1000);
// The ITEs delay is - afaics - by default big enough to cover this
sendComponentSupportToAUT(technicalTypeMapping);
}
/**
* send the list of supported components to the AUT
*
* @param technicalTypeMapping
* the technicalTypeMapping to use
*/
private void sendComponentSupportToAUT(
Map<ComponentClass, String> technicalTypeMapping)
throws CommunicationException {
SendAUTListOfSupportedComponentsMessage message =
new SendAUTListOfSupportedComponentsMessage();
message.setTechTypeToTesterClassMapping(technicalTypeMapping);
message.setProfile(ProfileBuilder.getDefaultProfile());
send(message);
}
}