/******************************************************************************* * 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.impl; import java.awt.image.BufferedImage; import java.net.ConnectException; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.Validate; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jubula.client.AUT; import org.eclipse.jubula.client.Result; import org.eclipse.jubula.client.exceptions.ActionException; import org.eclipse.jubula.client.exceptions.CheckFailedException; import org.eclipse.jubula.client.exceptions.CommunicationException; import org.eclipse.jubula.client.exceptions.ComponentNotFoundException; import org.eclipse.jubula.client.exceptions.ConfigurationException; import org.eclipse.jubula.client.exceptions.ExecutionException; import org.eclipse.jubula.client.exceptions.ExecutionExceptionHandler; import org.eclipse.jubula.client.internal.AUTConnection; import org.eclipse.jubula.client.internal.BaseConnection.NotConnectedException; import org.eclipse.jubula.client.internal.Synchronizer; import org.eclipse.jubula.client.internal.exceptions.ConnectionException; import org.eclipse.jubula.communication.CAP; import org.eclipse.jubula.communication.internal.IExceptionHandler; import org.eclipse.jubula.communication.internal.message.CAPTestMessage; import org.eclipse.jubula.communication.internal.message.CAPTestResponseMessage; import org.eclipse.jubula.communication.internal.message.Message; import org.eclipse.jubula.communication.internal.message.MessageCap; import org.eclipse.jubula.communication.internal.message.MessageParam; import org.eclipse.jubula.communication.internal.message.SetProfileMessage; import org.eclipse.jubula.communication.internal.message.TakeScreenshotMessage; import org.eclipse.jubula.communication.internal.message.TakeScreenshotResponseMessage; import org.eclipse.jubula.communication.internal.message.UnknownMessageException; import org.eclipse.jubula.toolkit.ToolkitInfo; import org.eclipse.jubula.toolkit.internal.AbstractToolkitInfo; import org.eclipse.jubula.tools.AUTIdentifier; import org.eclipse.jubula.tools.Profile; import org.eclipse.jubula.tools.internal.constants.StringConstants; import org.eclipse.jubula.tools.internal.i18n.I18n; import org.eclipse.jubula.tools.internal.objects.event.TestErrorEvent; import org.eclipse.jubula.tools.internal.registration.AutIdentifier; import org.eclipse.jubula.tools.internal.serialisation.SerializedImage; import org.eclipse.jubula.tools.internal.xml.businessmodell.ComponentClass; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** @author BREDEX GmbH */ public class AUTImpl implements AUT { /** the logger */ private static Logger log = LoggerFactory.getLogger(AUTImpl.class); /** the AUT identifier */ @NonNull private AutIdentifier m_autID; /** the instance */ private AUTConnection m_instance; /** the toolkit specific information */ private AbstractToolkitInfo m_information; /** the exception handler */ private ExecutionExceptionHandler m_handler; /** */ private boolean m_logToConsole; /** * Constructor * * @param autID * the identifier to use for connection * @param information * the toolkit information */ public AUTImpl( @NonNull AutIdentifier autID, @NonNull ToolkitInfo information) { Validate.notNull(autID, "The AUT-Identifier must not be null."); //$NON-NLS-1$ Validate.notNull(information, "The toolkit information must not be null."); //$NON-NLS-1$ m_autID = autID; setToolkitInformation((AbstractToolkitInfo)information); } /** {@inheritDoc} */ public void connect() throws CommunicationException { connect(0); } /** {@inheritDoc} */ public void connect(int timeOut) throws CommunicationException { connectImpl(timeOut); } /** * @param timeOut if 0 then the BaseAUTConnection.CONNECT_TO_AUT_TIMEOUT will be used * @throws CommunicationException */ private void connectImpl(int timeOut) throws CommunicationException { if (!isConnected()) { final Map<ComponentClass, String> typeMapping = getInformation().getTypeMapping(); try { m_instance = AUTConnection.getInstance(); m_instance.connectToAut(m_autID, typeMapping, timeOut); if (!isConnected()) { throw new CommunicationException( new ConnectException( "Could not connect to AUT: " //$NON-NLS-1$ + m_autID.getID() + ".")); //$NON-NLS-1$ } } catch (ConnectionException e) { log.error(e.getLocalizedMessage(), e); throw new CommunicationException(e); } } else { throw new IllegalStateException("AUT connection is already made"); //$NON-NLS-1$ } } /** {@inheritDoc} */ public void disconnect() { if (isConnected()) { m_instance.close(); } else { throw new IllegalStateException("AUT connection is already disconnected"); //$NON-NLS-1$ } } /** {@inheritDoc} */ public boolean isConnected() { return m_instance != null ? m_instance.isConnected() : false; } /** {@inheritDoc} */ @NonNull public AUTIdentifier getIdentifier() { return m_autID; } /** @param information the toolkit information to set */ private void setToolkitInformation(AbstractToolkitInfo information) { m_information = information; } /** * @return the information */ public AbstractToolkitInfo getInformation() { return m_information; } /** {@inheritDoc} */ @NonNull public <T> Result<T> execute(@NonNull CAP cap, @Nullable T payload) throws ExecutionException, CommunicationException { Validate.notNull(cap, "The CAP must not be null."); //$NON-NLS-1$ AUTAgentImpl.checkConnected(this); final ResultImpl<T> result = new ResultImpl<T>(cap, payload); try { CAPTestMessage capTestMessage = new CAPTestMessage( (MessageCap) cap); logCAPtoConsole(capTestMessage); m_instance.send(capTestMessage); Object exchange = Synchronizer.instance().exchange(null); if (exchange instanceof CAPTestResponseMessage) { CAPTestResponseMessage response = (CAPTestResponseMessage) exchange; processResponse(response, result); result.setOK(true); } else { log.error("Unexpected response received: " //$NON-NLS-1$ + String.valueOf(exchange)); } } catch (NotConnectedException e) { throw new CommunicationException(e); } catch (UnknownMessageException e) { log.error(e.getLocalizedMessage(), e); throw new CommunicationException(e); } catch (org.eclipse.jubula.tools.internal. exception.CommunicationException e) { log.error(e.getLocalizedMessage(), e); throw new CommunicationException(e); } catch (InterruptedException e) { log.error(e.getLocalizedMessage(), e); throw new CommunicationException(e); } catch (ExecutionException exec) { logExecutionException(exec, false); throw exec; } if (m_logToConsole && result.getException() != null) { ExecutionException exec = result.getException(); logExecutionException(exec, true); } return result; } /** * logs the CAP information to the console * @param capTestMessage the {@link CAPTestMessage} */ private void logCAPtoConsole(CAPTestMessage capTestMessage) { if (m_logToConsole) { StringBuilder builder = new StringBuilder(); MessageCap messcap = capTestMessage.getMessageCap(); builder.append("Method: " + messcap.getMethod() //$NON-NLS-1$ + StringConstants.SPACE); List<MessageParam> list = messcap.getMessageParams(); builder.append("Parameter: "); //$NON-NLS-1$ for (Iterator iterator = list.iterator(); iterator.hasNext();) { MessageParam messageParam = (MessageParam) iterator.next(); builder.append(StringConstants.QUOTE); builder.append(messageParam.getValue()); builder.append(StringConstants.QUOTE); if (iterator.hasNext()) { builder.append( StringConstants.COMMA + StringConstants.SPACE); } } log.debug(builder.toString()); System.out.println(builder.toString()); } } /** * this logs the occurred Exception to the console * @param exec the {@link ExecutionException} * @param catched if the exception was already handled via the {@link IExceptionHandler} */ private void logExecutionException(ExecutionException exec, boolean catched) { StringBuilder builder = new StringBuilder(); if (catched) { builder.append("Handled" + StringConstants.SPACE); //$NON-NLS-1$ } builder.append("Error occured" + StringConstants.SPACE); //$NON-NLS-1$ builder.append(exec.getClass().getSimpleName()); if (exec instanceof CheckFailedException) { CheckFailedException cfe = (CheckFailedException) exec; builder.append(StringConstants.NEWLINE); builder.append("Actual value: " + cfe.getActualValue()); //$NON-NLS-1$ } if (exec.getMessage() != null) { builder.append(StringConstants.NEWLINE + exec.getMessage()); } System.out.println(builder.toString()); log.info(builder.toString()); } /** * @param result * the result * @param response * the response to process */ private void processResponse(CAPTestResponseMessage response, @NonNull final ResultImpl result) throws ExecutionException { ExecutionException exception = null; if (response.hasTestErrorEvent()) { final TestErrorEvent event = response.getTestErrorEvent(); final String eventId = event.getId(); Map<String, Object> eventProps = event.getProps(); String description = null; if (eventProps.containsKey( TestErrorEvent.Property.DESCRIPTION_KEY)) { String key = (String) eventProps .get(TestErrorEvent.Property.DESCRIPTION_KEY); Object[] args = (Object[]) eventProps .get(TestErrorEvent.Property.PARAMETER_KEY); args = args != null ? args : new Object[0]; description = I18n.getString(key, args); } if (TestErrorEvent.ID.ACTION_ERROR.equals(eventId)) { exception = new ActionException(result, description); } else if (TestErrorEvent.ID.COMPONENT_NOT_FOUND.equals(eventId)) { exception = new ComponentNotFoundException(result, description); } else if (TestErrorEvent.ID.CONFIGURATION_ERROR.equals(eventId)) { exception = new ConfigurationException(result, description); } else if (TestErrorEvent.ID.VERIFY_FAILED.equals(eventId)) { Object actualValueObject = event.getProps().get( TestErrorEvent.Property.ACTUAL_VALUE_KEY); @NonNull String actualValue = "n/a"; //$NON-NLS-1$ if (actualValueObject instanceof String) { actualValue = (String)actualValueObject; } exception = new CheckFailedException( result, description, actualValue); } } else { result.setReturnValue(response.getReturnValue()); } result.setException(exception); if (exception != null) { if (m_handler != null) { m_handler.handle(exception); } else { throw exception; } } } /** {@inheritDoc} */ public void setHandler( @Nullable ExecutionExceptionHandler handler) { m_handler = handler; } /** {@inheritDoc} */ public BufferedImage getScreenshot() throws IllegalStateException { if (isConnected()) { Message message = new TakeScreenshotMessage(); try { m_instance.send(message); Object exchange = Synchronizer.instance().exchange(null); if (exchange instanceof TakeScreenshotResponseMessage) { TakeScreenshotResponseMessage response = (TakeScreenshotResponseMessage) exchange; return SerializedImage.computeImage( response.getScreenshot()); } log.error("Unexpected response received: " //$NON-NLS-1$ + String.valueOf(exchange)); } catch (NotConnectedException nce) { if (log.isErrorEnabled()) { log.error(nce.getLocalizedMessage(), nce); } } catch (IllegalArgumentException e) { if (log.isErrorEnabled()) { log.error(e.getLocalizedMessage(), e); } } catch (org.eclipse.jubula.tools.internal. exception.CommunicationException e) { if (log.isErrorEnabled()) { log.error(e.getLocalizedMessage(), e); } } catch (InterruptedException e) { if (log.isErrorEnabled()) { log.error(e.getLocalizedMessage(), e); } } } else { throw new IllegalStateException("No AUT connection!"); //$NON-NLS-1$ } return null; } @Override public void setProfile(Profile profile) throws IllegalArgumentException, IllegalStateException, CommunicationException { if (profile == null) { throw new IllegalArgumentException("Profile is null"); //$NON-NLS-1$ } if (isConnected()) { SetProfileMessage message = new SetProfileMessage(); message.setProfile((org.eclipse.jubula.tools .internal.xml.businessmodell.Profile) profile); try { m_instance.send(message); } catch (NotConnectedException nce) { if (log.isErrorEnabled()) { log.error(nce.getLocalizedMessage(), nce); } } catch (IllegalArgumentException e) { if (log.isErrorEnabled()) { log.error(e.getLocalizedMessage(), e); } } catch (org.eclipse.jubula.tools.internal. exception.CommunicationException e) { if (log.isErrorEnabled()) { log.error(e.getLocalizedMessage(), e); } } } else { throw new IllegalStateException("No AUT connection!"); //$NON-NLS-1$ } } /** * {@inheritDoc} */ public void setCAPtoConsoleLogging(boolean logCapToConsole) { m_logToConsole = logCapToConsole; } }