com.onedrive.sdk.http.OneDriveServiceException.java Source code

Java tutorial

Introduction

Here is the source code for com.onedrive.sdk.http.OneDriveServiceException.java

Source

// ------------------------------------------------------------------------------
// Copyright (c) 2015 Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// ------------------------------------------------------------------------------

package com.onedrive.sdk.http;

import com.onedrive.sdk.core.ClientException;
import com.onedrive.sdk.core.OneDriveErrorCodes;
import com.onedrive.sdk.options.HeaderOption;
import com.onedrive.sdk.serializer.ISerializer;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * An exception from the OneDrive service.
 */
public class OneDriveServiceException extends ClientException {

    /**
     * New line delimiter.
     */
    protected static final char NEW_LINE = '\n';

    /**
     * How truncated values are shown.
     */
    protected static final String TRUNCATION_MARKER = "[...]";

    /**
     * The maximum length for a single line string when trying to be brief.
     */
    protected static final int MAX_BREVITY_LENGTH = 50;

    /**
     * The number of bytes to display when showing byte array.
     */
    protected static final int MAX_BYTE_COUNT_BEFORE_TRUNCATION = 8;

    /**
     * The intent spacing on json based responses.
     */
    public static final int INDENT_SPACES = 3;

    /**
     * The internal server error threshold defined by http protocol.
     */
    public static final int INTERNAL_SERVER_ERROR = 500;

    /**
     * The OneDriveError response.
     */
    private final OneDriveErrorResponse mError;

    /**
     * The http method.
     */
    private final String mMethod;

    /**
     * The request url.
     */
    private final String mUrl;

    /**
     * The request headers.
     */
    private final List<String> mRequestHeaders;

    /**
     * The request body represented as a string.
     */
    private final String mRequestBody;

    /**
     * The http status code.
     */
    private final int mResponseCode;

    /**
     * The http status message.
     */
    private final String mResponseMessage;

    /**
     * The response headers.
     */
    private final List<String> mResponseHeaders;

    /**
     * Create a OneDrive service exception.
     * @param method The method that caused the exception.
     * @param url The url.
     * @param requestHeaders The request headers.
     * @param requestBody The request body.
     * @param responseCode The response code.
     * @param responseMessage The response message.
     * @param responseHeaders The response headers.
     * @param error The error response if available.
     */
    protected OneDriveServiceException(final String method, final String url, final List<String> requestHeaders,
            final String requestBody, final int responseCode, final String responseMessage,
            final List<String> responseHeaders, final OneDriveErrorResponse error) {
        super(responseMessage, null, null);
        mMethod = method;
        mUrl = url;
        mRequestHeaders = requestHeaders;
        mRequestBody = requestBody;
        mResponseCode = responseCode;
        mResponseMessage = responseMessage;
        mResponseHeaders = responseHeaders;
        mError = error;
    }

    @Override
    public String getMessage() {
        return getMessage(false);
    }

    /**
     * Gets the message for this exception.
     * @param verbose If the message should be brief or more verbose.
     * @return The message.
     */
    public String getMessage(final boolean verbose) {
        final StringBuilder sb = new StringBuilder();
        if (mError != null && mError.error != null) {
            sb.append("Error code: ").append(mError.error.code).append(NEW_LINE);
            sb.append("Error message: ").append(mError.error.message).append(NEW_LINE);
            sb.append(NEW_LINE);
        }
        // Request information
        sb.append(mMethod).append(' ').append(mUrl).append(NEW_LINE);
        for (final String header : mRequestHeaders) {
            if (verbose) {
                sb.append(header);
            } else {
                final String truncatedHeader = header.substring(0, Math.min(MAX_BREVITY_LENGTH, header.length()));
                sb.append(truncatedHeader);
                if (truncatedHeader.length() == MAX_BREVITY_LENGTH) {
                    sb.append(TRUNCATION_MARKER);
                }
            }
            sb.append(NEW_LINE);
        }
        if (mRequestBody != null) {
            if (verbose) {
                sb.append(mRequestBody);
            } else {
                final int bodyLength = Math.min(MAX_BREVITY_LENGTH, mRequestBody.length());
                final String truncatedBody = mRequestBody.substring(0, bodyLength);
                sb.append(truncatedBody);
                if (truncatedBody.length() == MAX_BREVITY_LENGTH) {
                    sb.append(TRUNCATION_MARKER);
                }
            }
        }
        sb.append(NEW_LINE).append(NEW_LINE);

        // Response information
        sb.append(mResponseCode).append(" : ").append(mResponseMessage).append(NEW_LINE);
        for (final String header : mResponseHeaders) {
            if (verbose) {
                sb.append(header).append(NEW_LINE);
            } else {
                if (header.toLowerCase(Locale.ROOT).startsWith("x-throwsite")) {
                    sb.append(header).append(NEW_LINE);
                }
            }
        }
        if (verbose && mError != null && mError.rawObject != null) {
            try {
                final JSONObject jsonObject = new JSONObject(mError.rawObject.toString());
                sb.append(jsonObject.toString(INDENT_SPACES)).append(NEW_LINE);
            } catch (final JSONException ignored) {
                sb.append("[Warning: Unable to parse error message body]").append(NEW_LINE);
            }
        } else {
            sb.append(TRUNCATION_MARKER).append(NEW_LINE).append(NEW_LINE);
            sb.append("[Some information was truncated for brevity, enable debug logging for more details]");
        }
        return sb.toString();
    }

    /**
     * Gets the error message from the OneDrive service object.
     * @return The error message.
     */
    public OneDriveError getServiceError() {
        return mError.error;
    }

    @Override
    public boolean isError(final OneDriveErrorCodes expectedCode) {
        if (getServiceError() != null) {
            return getServiceError().isError(expectedCode);
        }
        return false;
    }

    /**
     * Creates a OneDrive service exception from a given failed http request.
     * @param request The request that resulted in this failure.
     * @param serializable The serialized object that was sent with this request.
     * @param serializer The serializer to re-create the option in its over the wire state.
     * @param connection The connection that was used to extract the response information from.
     * @param <T> The type of the serializable object.
     * @return The new OneDriveServiceException instance.
     * @throws IOException An exception occurs if there were any problems processing the connection.
     */
    public static <T> OneDriveServiceException createFromConnection(final IHttpRequest request,
            final T serializable, final ISerializer serializer, final IConnection connection) throws IOException {
        final String method = connection.getRequestMethod();
        final String url = request.getRequestUrl().toString();
        final List<String> requestHeaders = new LinkedList<>();
        for (final HeaderOption option : request.getHeaders()) {
            requestHeaders.add(option.getName() + " : " + option.getValue());
        }
        final String requestBody;
        if (serializable instanceof byte[]) {
            final byte[] bytes = (byte[]) serializable;
            StringBuilder sb = new StringBuilder();
            sb.append("byte[").append(bytes.length).append("]");

            sb.append(" {");
            for (int i = 0; i < MAX_BYTE_COUNT_BEFORE_TRUNCATION && i < bytes.length; i++) {
                sb.append(bytes[i]).append(", ");
            }
            if (bytes.length > MAX_BYTE_COUNT_BEFORE_TRUNCATION) {
                sb.append(TRUNCATION_MARKER).append("}");
            }
            requestBody = sb.toString();
        } else if (serializable != null) {
            requestBody = serializer.serializeObject(serializable);
        } else {
            requestBody = null;
        }

        final int responseCode = connection.getResponseCode();
        final List<String> responseHeaders = new LinkedList<>();
        final Map<String, String> headers = connection.getHeaders();
        for (final String key : headers.keySet()) {
            final String fieldPrefix;
            if (key == null) {
                fieldPrefix = "";
            } else {
                fieldPrefix = key + " : ";
            }
            responseHeaders.add(fieldPrefix + headers.get(key));
        }

        final String responseMessage = connection.getResponseMessage();
        final String rawOutput = DefaultHttpProvider.streamToString(connection.getInputStream());
        OneDriveErrorResponse error;
        try {
            error = serializer.deserializeObject(rawOutput, OneDriveErrorResponse.class);
        } catch (final Exception ex) {
            error = new OneDriveErrorResponse();
            error.error = new OneDriveError();
            error.error.code = "Unable to parse error response message";
            error.error.message = "Raw error: " + rawOutput;
            error.error.innererror = new OneDriveInnerError();
            error.error.innererror.code = ex.getMessage();
        }

        if (responseCode >= INTERNAL_SERVER_ERROR) {
            return new OneDriveFatalServiceException(method, url, requestHeaders, requestBody, responseCode,
                    responseMessage, responseHeaders, error);
        }

        return new OneDriveServiceException(method, url, requestHeaders, requestBody, responseCode, responseMessage,
                responseHeaders, error);
    }
}