/* MonkeyTalk - a cross-platform functional testing tool
Copyright (C) 2012 Gorilla Logic, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package com.gorillalogic.monkeytalk.sender;
import java.io.File;
import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import com.gorillalogic.monkeytalk.server.JsonServer.HttpStatus;
import com.gorillalogic.monkeytalk.utils.Base64;
/**
* The response from an HTTP POST, returned by the {@link CommandSender} during playback or
* recording.
*/
public class Response {
private int code;
private String body;
private ResponseStatus status;
private String message;
private String warning;
private String image;
private File imageFile = null;
/**
* Instantiate a {@code 200 OK} response with an empty body.
*/
public Response() {
this(HttpStatus.OK.getCode(), null);
}
/**
* Instantiate a response with a code of {@code 200 OK} and the given body.
*
* @param body
* the JSON body
*/
public Response(String body) {
this(HttpStatus.OK.getCode(), body);
}
/**
* <p>
* Instantiate a response with the given HTTP status code and JSON body as returned by an HTTP
* POST. The JSON body is parsed into a {@link ResponseStatus} plus a message.
* </p>
*
* <p>
* For example, given a code of {@code 200 OK} and a body of
* <code>{result:"OK",message:"foo"}</code>, the status is {@link ResponseStatus#OK} and the
* message is {@code "foo"}.
* </p>
*
* @see ResponseStatus
*
* @param code
* the HTTP status code
* @param body
* the JSON body
*/
public Response(int code, String body) {
this.code = code;
this.body = body;
status = ResponseStatus.ERROR;
if (code != HttpStatus.OK.getCode()) {
JSONObject json = getBodyAsJSON();
if (json != null && json.has("message")) {
try {
JSONObject msg = json.getJSONObject("message");
message = msg.optString("message", null);
warning = msg.optString("warning", null);
image = msg.optString(msg.has("screenshot") ? "screenshot" : "image", null);
} catch (JSONException ex) {
message = json.optString("message", null);
}
} else {
message = body;
}
} else {
if (body == null) {
status = ResponseStatus.OK;
} else {
JSONObject json = getBodyAsJSON();
if (json != null) {
String result = json.optString("result");
if (result != null) {
if (result.equalsIgnoreCase("ok")) {
status = ResponseStatus.OK;
} else if (result.equalsIgnoreCase("failure")) {
status = ResponseStatus.FAILURE;
}
}
try {
JSONObject msg = json.getJSONObject("message");
message = msg.optString("message", null);
warning = msg.optString("warning", null);
image = msg.optString(msg.has("screenshot") ? "screenshot" : "image", null);
} catch (JSONException ex) {
message = json.optString("message", null);
warning = json.optString("warning", null);
image = json.optString(json.has("screenshot") ? "screenshot" : "image",
null);
}
} else {
message = body;
}
}
}
}
public Response(ResponseStatus status, String message, String warning, String image) {
this.status = status;
this.message = message;
this.warning = warning;
this.image = image;
code = HttpStatus.OK.getCode();
JSONObject msg = new JSONObject();
try {
msg.put("result", status.toString());
if (warning == null && image == null) {
msg.putOpt("message", message);
} else {
JSONObject msgObj = new JSONObject();
msgObj.putOpt("message", message);
msgObj.putOpt("warning", warning);
msgObj.putOpt("screenshot", image);
msg.put("message", msgObj);
}
body = msg.toString();
} catch (JSONException ex) {
body = null;
}
}
/**
* Get the HTTP status code.
*
* @return the HTTP status code
*/
public int getCode() {
return code;
}
/**
* Get the JSON body as a string.
*
* @return the JSON body
*/
public String getBody() {
return body;
}
/**
* Get the JSON body as a {@code JSONObject} object.
*
* @return the JSON body
*/
public JSONObject getBodyAsJSON() {
if (body == null) {
return null;
}
try {
return new JSONObject(body);
} catch (JSONException ex) {
return null;
}
}
/**
* Get the response status, which is one of OK, ERROR, or FAILURE.
*
* @return the response status
*/
public ResponseStatus getStatus() {
return status;
}
/**
* Get the response message, typically everything under the {@code message} key in the JSON
* body.
*
* @return the response message
*/
public String getMessage() {
return message;
}
/**
* Get the response warning, typically everything under the {@code warning} key in the JSON
* body.
*
* @return the response message
*/
public String getWarning() {
return warning;
}
/**
* Get the response image, typically everything under the {@code image} key in the JSON body.
*
* @return the response message
*/
public String getImage() {
return image;
}
public File getImageFile() {
if (imageFile != null) {
return imageFile;
}
if (image == null) {
return null;
}
try {
imageFile = File.createTempFile("screenshot_", ".png");
Base64.decodeToFile(image, imageFile.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException("Error getting image: " + e.getMessage());
}
return imageFile;
}
@Override
public String toString() {
return status + (message != null && message.length() > 0 ? " : " + message : "");
}
/**
* Enum for the three possible Response statuses: OK, ERROR, or FAILURE.
*/
public enum ResponseStatus {
/**
* Successfully played MonkeyTalk command.
*/
OK,
/**
* Error playing MonkeyTalk command (halt playback).
*/
ERROR,
/**
* Failed to verify MonkeyTalk command (fail the test).
*/
FAILURE;
}
public static class Builder {
private ResponseStatus status;
private String message;
private String warning;
private String image;
public Builder() {
this(null);
}
public Builder(String message) {
this.status = ResponseStatus.OK;
this.message = message;
}
public Builder ok() {
this.status = ResponseStatus.OK;
return this;
}
public Builder failure() {
this.status = ResponseStatus.FAILURE;
return this;
}
public Builder error() {
this.status = ResponseStatus.ERROR;
return this;
}
public Builder message(String message) {
this.message = message;
return this;
}
public Builder warning(String warning) {
this.warning = warning;
return this;
}
public Builder image(String image) {
this.image = image;
return this;
}
public Response build() {
return new Response(status, message, warning, image);
}
}
public void setImageFile(File image) {
imageFile = image;
}
}