001package com.box.sdk;
002
003import com.eclipsesource.json.Json;
004import com.eclipsesource.json.JsonObject;
005import com.eclipsesource.json.ParseException;
006import java.io.IOException;
007import java.io.InputStreamReader;
008import java.util.List;
009import java.util.Map;
010
011/**
012 * Used to read HTTP responses containing JSON from the Box API.
013 *
014 * <p>This request type extends BoxAPIResponse to provide additional functionality for handling JSON strings. It reads
015 * the response body into a string and allows the JSON in the response to be logged.</p>
016 */
017public class BoxJSONResponse extends BoxAPIResponse {
018    private static final int BUFFER_SIZE = 8192;
019    private JsonObject jsonObject;
020
021    /**
022     * Constructs a BoxJSONResponse without an associated HttpURLConnection.
023     */
024    public BoxJSONResponse() {
025        super();
026    }
027
028    BoxJSONResponse(BoxAPIResponse response) {
029        this(
030            response.getResponseCode(),
031            response.getRequestMethod(),
032            response.getRequestUrl(),
033            response.getHeaders(),
034            new JsonObject()
035        );
036    }
037
038    /**
039     * Constructs a BoxAPIResponse with an http response code and response body.
040     *
041     * @param responseCode http response code
042     * @param headers  map of http headers
043     * @param body         response body as Json Object
044     */
045    public BoxJSONResponse(int responseCode,
046                           String requestMethod,
047                           String requestUrl,
048                           Map<String, List<String>> headers,
049                           JsonObject body
050    ) {
051        super(responseCode, requestMethod, requestUrl, headers);
052        this.jsonObject = body;
053    }
054
055    /**
056     * Get response as Json Object.
057     *
058     * @return response as JsonObject
059     */
060    public JsonObject getJsonObject() {
061        if (this.jsonObject != null) {
062            return this.jsonObject;
063        } else {
064            return Json.parse(this.getJSON()).asObject();
065        }
066    }
067
068    /**
069     * Gets the body of the response as a JSON string. When this method is called, the response's body will be read and
070     * the response will be disconnected, meaning that the stream returned by {@link #getBody} can no longer be used.
071     *
072     * @return the body of the response as a JSON string.
073     */
074    public String getJSON() {
075        if (this.jsonObject != null) {
076            return this.jsonObject.toString();
077        } else if (this.getBody() == null) {
078            return null;
079        } else {
080            InputStreamReader reader = new InputStreamReader(this.getBody(), StandardCharsets.UTF_8);
081            StringBuilder builder = new StringBuilder();
082            char[] buffer = new char[BUFFER_SIZE];
083
084            try {
085                int read = reader.read(buffer, 0, BUFFER_SIZE);
086                while (read != -1) {
087                    builder.append(buffer, 0, read);
088                    read = reader.read(buffer, 0, BUFFER_SIZE);
089                }
090
091                this.close();
092                reader.close();
093            } catch (IOException e) {
094                throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e);
095            }
096            String jsonAsString = builder.toString();
097            try {
098                this.jsonObject = Json.parse(jsonAsString).asObject();
099            } catch (ParseException e) {
100                throw new RuntimeException("Error parsing JSON:\n" + jsonAsString, e);
101            }
102            return jsonAsString;
103        }
104    }
105
106    @Override
107    protected String bodyToString() {
108        String bodyString = super.bodyToString();
109        if (bodyString == null) {
110            return this.getJSON();
111        } else {
112            return bodyString;
113        }
114    }
115}