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