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