/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.panels.teststeps.amf;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.TestCaseConfig;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.teststeps.AMFRequestTestStep;
import com.eviware.soapui.model.iface.Submit;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.iface.SubmitListener;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.types.StringToStringsMap;
import flex.messaging.io.amf.client.exceptions.ClientStatusException;
import flex.messaging.io.amf.client.exceptions.ServerStatusException;
import java.util.List;
import java.util.concurrent.Future;
public class AMFSubmit implements Submit, Runnable {
public static final String AMF_CONNECTION = "AMF_CONNECTION";
private volatile Future<?> future;
private SubmitContext context;
private Status status;
private SubmitListener[] listeners;
private Exception error;
private long timestamp;
private final AMFRequest request;
private AMFResponse response;
private AMFCredentials credentials;
public AMFSubmit(AMFRequest request, SubmitContext submitContext, boolean async) {
this.request = request;
this.context = submitContext;
List<SubmitListener> regListeners = SoapUI.getListenerRegistry().getListeners(SubmitListener.class);
SubmitListener[] submitListeners = request.getSubmitListeners();
this.listeners = new SubmitListener[submitListeners.length + regListeners.size()];
for (int c = 0; c < submitListeners.length; c++) {
this.listeners[c] = submitListeners[c];
}
for (int c = 0; c < regListeners.size(); c++) {
this.listeners[submitListeners.length + c] = regListeners.get(c);
}
error = null;
status = Status.INITIALIZED;
timestamp = System.currentTimeMillis();
if (async) {
future = SoapUI.getThreadPool().submit(this);
} else {
run();
}
}
public void cancel() {
if (status == Status.CANCELED) {
return;
}
SoapUI.log.info("Canceling request..");
status = Status.CANCELED;
for (int i = 0; i < listeners.length; i++) {
try {
listeners[i].afterSubmit(this, context);
} catch (Throwable e) {
SoapUI.logError(e);
}
}
}
public Status waitUntilFinished() {
if (future != null) {
if (!future.isDone()) {
try {
future.get();
} catch (Exception e) {
SoapUI.logError(e);
}
}
} else {
throw new RuntimeException("cannot wait on null future");
}
return getStatus();
}
public void run() {
try {
for (int i = 0; i < listeners.length; i++) {
if (!listeners[i].beforeSubmit(this, context)) {
status = Status.CANCELED;
SoapUI.log.error("listener cancelled submit..");
return;
}
}
status = Status.RUNNING;
Object responseContent = executeAmfCall(getRequest());
createResponse(responseContent);
if (status != Status.CANCELED && status != Status.ERROR) {
status = Status.FINISHED;
}
} catch (Exception e) {
UISupport.showErrorMessage("There's been an error in executing query " + e.toString());
error = e;
} finally {
if (status != Status.CANCELED) {
for (int i = 0; i < listeners.length; i++) {
try {
listeners[i].afterSubmit(this, context);
} catch (Throwable e) {
SoapUI.logError(e);
}
}
}
}
}
protected void createResponse(Object responseContent) {
try {
response = new AMFResponse(request, context, responseContent);
response.setTimestamp(timestamp);
response.setTimeTaken(System.currentTimeMillis() - timestamp);
} catch (Exception e) {
SoapUI.logError(e);
}
}
private Object executeAmfCall(AMFRequest amfRequest) throws ClientStatusException, ServerStatusException {
SoapUIAMFConnection amfConnection = null;
try {
amfConnection = getConnection(amfRequest);
addAmfHeaders(amfRequest, amfConnection);
addHttpHeaders(amfRequest, amfConnection);
Object result = amfConnection.call(context, amfRequest.getAmfCall(), amfRequest.argumentsToArray());
return result;
} catch (Exception e) {
SoapUI.logError(e);
error = e;
status = Status.ERROR;
} finally {
amfRequest.clearArguments();
if (context.getModelItem() instanceof AMFRequestTestStep) {
if (credentials != null && credentials.isLoggedIn()) {
credentials.logout();
credentials = null;
} else {
amfConnection.close();
}
}
}
return null;
}
private SoapUIAMFConnection getConnection(AMFRequest amfRequest) throws Exception {
SoapUIAMFConnection amfConnection = null;
if (isAuthorisationEnabled(amfRequest) && (context.getModelItem() instanceof WsdlTestCase)) {
if ((amfConnection = (SoapUIAMFConnection) context.getProperty(AMF_CONNECTION)) != null) {
return amfConnection;
} else {
throw new Exception("amf session connection error! ");
}
} else if (isAuthorisationEnabled(amfRequest) && (context.getModelItem() instanceof AMFRequestTestStep)) {
String endpoint = context.expand(getTestCaseConfig(amfRequest).getAmfEndpoint());
String username = context.expand(getTestCaseConfig(amfRequest).getAmfLogin());
String password = context.expand(getTestCaseConfig(amfRequest).getAmfPassword());
if (StringUtils.hasContent(endpoint) && StringUtils.hasContent(username)) {
credentials = new AMFCredentials(endpoint, username, password, context);
amfConnection = credentials.login();
} else {
amfConnection = new SoapUIAMFConnection();
amfConnection.connect(context.expand(amfRequest.getEndpoint()));
}
context.setProperty(AMF_CONNECTION, amfConnection);
return amfConnection;
} else {
amfConnection = new SoapUIAMFConnection();
amfConnection.connect(context.expand(amfRequest.getEndpoint()));
return amfConnection;
}
}
private boolean isAuthorisationEnabled(AMFRequest amfRequest) {
return getTestCaseConfig(amfRequest).getAmfAuthorisation();
}
private TestCaseConfig getTestCaseConfig(AMFRequest amfRequest) {
return amfRequest.getTestStep().getTestCase().getConfig();
}
private void addHttpHeaders(AMFRequest amfRequest, SoapUIAMFConnection amfConnection) {
StringToStringsMap httpHeaders = amfRequest.getHttpHeaders();
if (httpHeaders != null) {
for (String key : httpHeaders.getKeys()) {
for (String value : httpHeaders.get(key)) {
amfConnection.addHttpRequestHeader(key, context.expand(value));
}
}
}
}
private void addAmfHeaders(AMFRequest amfRequest, SoapUIAMFConnection amfConnection) {
if (amfRequest.getAmfHeaders() != null) {
for (String key : amfRequest.getAmfHeaders().keySet()) {
Object data = amfRequest.getAmfHeaders().get(key);
if (data instanceof String) {
data = context.expand((String) data);
}
amfConnection.addAmfHeader(key, data);
}
}
}
public Exception getError() {
return error;
}
public AMFRequest getRequest() {
return request;
}
public AMFResponse getResponse() {
return response;
}
public Status getStatus() {
return status;
}
}