001package com.box.sdk;
002
003import java.io.IOException;
004import java.io.InputStreamReader;
005import java.net.HttpURLConnection;
006import java.util.Map;
007
008import com.eclipsesource.json.JsonObject;
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     * @param  connection a connection that has already sent a request to the API.
030     */
031    public BoxJSONResponse(HttpURLConnection connection) {
032        super(connection);
033    }
034
035    /**
036     * Constructs a BoxAPIResponse with an http response code and response body.
037     * @param responseCode http response code
038     * @param httpHeaders map of http headers
039     * @param body response body as Json Object
040     */
041    public BoxJSONResponse(int responseCode, Map<String, String> httpHeaders, JsonObject body) {
042        super(responseCode, httpHeaders);
043        this.jsonObject = body;
044    }
045
046    /**
047     * Get response as Json Object.
048     * @return response as JsonObject
049     */
050    public JsonObject getJsonObject() {
051        if (this.jsonObject != null) {
052            return this.jsonObject;
053        } else {
054            return JsonObject.readFrom(this.getJSON());
055        }
056    }
057
058    /**
059     * Gets the body of the response as a JSON string. When this method is called, the response's body will be read and
060     * the response will be disconnected, meaning that the stream returned by {@link #getBody} can no longer be used.
061     * @return the body of the response as a JSON string.
062     */
063    public String getJSON() {
064        if (this.jsonObject != null) {
065            return this.jsonObject.toString();
066        } else {
067            InputStreamReader reader = new InputStreamReader(this.getBody(), StandardCharsets.UTF_8);
068            StringBuilder builder = new StringBuilder();
069            char[] buffer = new char[BUFFER_SIZE];
070
071            try {
072                int read = reader.read(buffer, 0, BUFFER_SIZE);
073                while (read != -1) {
074                    builder.append(buffer, 0, read);
075                    read = reader.read(buffer, 0, BUFFER_SIZE);
076                }
077
078                this.disconnect();
079                reader.close();
080            } catch (IOException e) {
081                throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e);
082            }
083            this.jsonObject = JsonObject.readFrom(builder.toString());
084            return builder.toString();
085        }
086    }
087
088    @Override
089    protected String bodyToString() {
090        String bodyString = super.bodyToString();
091        if (bodyString == null) {
092            return this.getJSON();
093        } else {
094            return bodyString;
095        }
096    }
097}