/*******************************************************************************
* Copyright (c) 2013 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.rc.javafx;
import java.awt.Rectangle;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.Callable;
import org.eclipse.jubula.communication.internal.message.AUTServerStateMessage;
import org.eclipse.jubula.rc.common.AUTServer;
import org.eclipse.jubula.rc.common.driver.IRobot;
import org.eclipse.jubula.rc.common.exception.ComponentNotFoundException;
import org.eclipse.jubula.rc.common.listener.BaseAUTListener;
import org.eclipse.jubula.rc.common.listener.DisabledCheckListener;
import org.eclipse.jubula.rc.common.listener.DisabledRecordListener;
import org.eclipse.jubula.rc.common.registration.IRegisterAut;
import org.eclipse.jubula.rc.javafx.components.CurrentStages;
import org.eclipse.jubula.rc.javafx.driver.EventThreadQueuerJavaFXImpl;
import org.eclipse.jubula.rc.javafx.driver.RobotFactoryJavaFXImpl;
import org.eclipse.jubula.rc.javafx.listener.AbstractFXAUTEventHandler;
import org.eclipse.jubula.rc.javafx.listener.ComponentHandler;
import org.eclipse.jubula.rc.javafx.listener.MappingListener;
import org.eclipse.jubula.tools.internal.constants.AUTServerExitConstants;
import org.eclipse.jubula.tools.internal.exception.JBVersionException;
import org.eclipse.jubula.tools.internal.objects.IComponentIdentifier;
import org.eclipse.jubula.tools.internal.utils.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.stage.Stage;
import javafx.stage.Window;
/**
* The AutServer controlling the AUT. <br>
* A quasi singleton: the instance is created from main(). <br>
* Expected arguments to main are, see also
* StartAUTServerCommand.createCmdArray():
* <ul>
* <li>The name of host the client is running on, must be InetAddress conform.</li>
* <li>The port the JubulaClient is listening to.</li>
* <li>The main class of the AUT.</li>
* <li>Any further arguments are interpreted as arguments to the AUT.</li>
* <ul>
* When a connection to the JubulaClient could made, any errors will send as a
* message to the JubulaClient.
*
* Changing the mode to OBJECT_MAPPING results in installing an
* JavaFXEventFilter on the assumed primary stage, which listens to the mouse-
* and key.events relevant for OBJECT_MAPPING.
*
* Changing the mode removes the installed MappingListener.
*
* @author BREDEX GmbH
* @created 24.09.2013
*/
public class JavaFXAUTServer extends AUTServer {
/** the logger */
private static Logger log = LoggerFactory.getLogger(AUTServer.class);
/**
* constructor instantiates the listeners
*/
public JavaFXAUTServer() {
super(new MappingListener(),
new DisabledRecordListener(),
new DisabledCheckListener());
}
@Override
protected void addToolkitEventListener(BaseAUTListener listener) {
if (listener instanceof AbstractFXAUTEventHandler) {
addToolkitEventListener((AbstractFXAUTEventHandler) listener);
}
}
/**
* Adds a handler to the stage
*
* @param handler
* the handler
*/
private void addToolkitEventListener(AbstractFXAUTEventHandler handler) {
List<? extends Window> windows =
ComponentHandler.getAssignableFrom(Window.class);
for (final Window win : windows) {
handler.addHandler(win);
}
CurrentStages.addStagesListener(handler);
}
@Override
protected void addToolkitEventListeners() {
addToolkitEventListener(new ComponentHandler());
}
@Override
protected void removeToolkitEventListener(BaseAUTListener listener) {
if (listener instanceof AbstractFXAUTEventHandler) {
removeToolkitEventListener((AbstractFXAUTEventHandler) listener);
}
}
/**
* removes a handler from the stage
*
* @param handler
* the handler
*/
private void removeToolkitEventListener(AbstractFXAUTEventHandler handler) {
List<? extends Stage> stages =
ComponentHandler.getAssignableFrom(Stage.class);
for (Stage stage : stages) {
handler.removeHandler(stage);
}
CurrentStages.removeStagesListener(handler);
}
@Override
protected void startTasks() throws ExceptionInInitializerError,
InvocationTargetException, NoSuchMethodException {
addToolKitEventListenerToAUT();
invokeAUT();
}
@Override
public IRobot<Rectangle> getRobot() {
return RobotFactoryJavaFXImpl.INSTANCE.getRobot();
}
/**
* {@inheritDoc}
*/
public Object findComponent(IComponentIdentifier ci, int timeout)
throws ComponentNotFoundException, IllegalArgumentException {
return ComponentHandler.findComponent(ci, true, timeout);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isComponentDisappeared(IComponentIdentifier ci, int timeout)
throws ComponentNotFoundException, IllegalArgumentException {
return ComponentHandler.isComponentDisappeared(ci, timeout);
}
/**
* Tries to schedule an empty runnable in the JavaFX-Thread
*
* @return true if scheduling was successful and the toolkit is therefore
* initialized, false otherwise
*/
private boolean checkInitialization() {
try {
return EventThreadQueuerJavaFXImpl.invokeAndWait("getStageByTitle", //$NON-NLS-1$
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
// Do nothing, we are just checking if an Exception
// is thrown when the task is scheduled
return true;
}
});
} catch (IllegalStateException e) {
// Do nothing, toolkit not initialized
return false;
}
}
@Override
protected void registerAutinAgent(IRegisterAut autReg)
throws JBVersionException {
new Thread(new Runnable() {
@Override
public void run() {
do {
TimeUtil.delay(100);
// do nothing, wait to get the toolkit initialized
} while (!checkInitialization());
try {
JavaFXAUTServer.super.registerAutinAgent(autReg);
} catch (JBVersionException e) {
sendExitReason(e,
AUTServerStateMessage.EXIT_AUT_WRONG_CLASS_VERSION);
System.exit(AUTServerExitConstants.EXIT_UNKNOWN_ITE_CLIENT);
}
}
}).start();
}
@Override
protected void connectToITE() {
new Thread(new Runnable() {
@Override
public void run() {
do {
TimeUtil.delay(100);
// do nothing, wait to get the toolkit initialized
} while (!checkInitialization());
JavaFXAUTServer.super.connectToITE();
}
}).start();
}
}