com.microsoft.office365.meetingmgr.HttpHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.office365.meetingmgr.HttpHelper.java

Source

/*
 * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license.
 * See LICENSE in the project root for license information.
 */
package com.microsoft.office365.meetingmgr;

import android.util.Log;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.office365.meetingmgr.Models.User;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBaseHC4;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * Extends functionality of HttpHelperBase by providing app-specific and OData-specific features
 */

@SuppressWarnings("deprecation")
public class HttpHelper extends HttpHelperBase {

    private static boolean mUnified = true;

    private static String mBaseUri;
    private boolean mLogDisabled;
    private String mErrorMessage;

    public HttpHelper() {
        mBaseUri = getOfficeEndPoint() + "Me/";
    }

    public void disableLog(boolean disable) {
        mLogDisabled = disable;
    }

    public String getErrorMessage() {
        return mErrorMessage;
    }

    public <TResult> PagedResult<TResult> getPagedItems(String uri, Class<TResult> clazz) {
        return doGetItems(uri, Integer.MAX_VALUE, 1, clazz);
    }

    public <TResult> List<TResult> getItems(String uri, int count, Class<TResult> clazz) {
        PagedResult<TResult> res = doGetItems(uri, count, Integer.MAX_VALUE, clazz);
        return res.list;
    }

    private <TResult> PagedResult<TResult> doGetItems(String uri, int itemCount, int pageCount,
            Class<TResult> clazz) {
        String fullUri = buildUri(uri);

        List<TResult> result = new ArrayList<>();
        ObjectMapper mapper = new JsonMapper();

        while (pageCount-- > 0 && itemCount > 0 && fullUri != null) {
            ODataListBase<TResult> list = createList(fullUri);
            list = getItem(fullUri, list.getClass());

            if (list == null) {
                return new PagedResult<>(null, null);
            }

            fullUri = list.getNextLink(fullUri);

            for (Object el : list.value) {
                --itemCount;
                result.add(mapper.convertValue(el, clazz));
            }
        }
        return new PagedResult<>(result, fullUri);
    }

    private <T> ODataListBase<T> createList(String uri) {
        if (HttpHelper.isUnified() || !uri.contains("graph")) {
            return new ODataList<>();
        } else {
            return new ODataListAAD<>();
        }
    }

    private static class ODataList<T> extends ODataListBase<T> {
        @JsonProperty("@odata.nextLink")
        public String NextLink;

        @Override
        public String getNextLink(String currentUri) {
            return NextLink;
        }
    }

    private static class ODataListAAD<T> extends ODataListBase<T> {
        @JsonProperty("odata.nextLink")
        public String NextLink;

        @Override
        public String getNextLink(String currentUri) {
            if (Utils.isNullOrEmpty(NextLink)) {
                return null;
            }

            String skiptoken = Utils.getToken(NextLink, "$skiptoken");
            if (skiptoken == null) {
                return null;
            }

            String nextUri = Utils.stripToken(currentUri, "&$skiptoken");
            nextUri = Utils.stripToken(nextUri, "&previous-page");

            if (nextUri.charAt(nextUri.length() - 1) != '&') {
                nextUri += '&';
            }

            nextUri += skiptoken;

            return nextUri;
        }
    }

    private abstract static class ODataListBase<T> {
        abstract String getNextLink(String currentUri);

        public List<T> value;
    }

    public static class PagedResult<TResult> {
        public final List<TResult> list;
        public final String nextUri;

        public PagedResult(List<TResult> list, String nextUri) {
            this.list = list;
            this.nextUri = nextUri;
        }
    }

    @Override
    protected String buildUri(String uri) {
        uri = super.buildUri(uri);

        if (uri.startsWith("http")) {
            return uri;
        }
        return mBaseUri + uri;
    }

    @Override
    protected CloseableHttpResponse executeRequest(HttpRequestBaseHC4 httpRequest)
            throws ExecutionException, InterruptedException, IOException {
        User user = Manager.Instance.getUser();
        if (user != null) {
            httpRequest.setHeader("AnchorMailbox", user.id);
        }

        setAuthHeader(httpRequest, false);
        CloseableHttpResponse response = super.executeRequest(httpRequest);

        if (needsTokenRefresh(response)) {
            setAuthHeader(httpRequest, true);

            // Repeat failed request with refreshed token
            response = super.executeRequest(httpRequest);
        }

        return response;
    }

    private void setAuthHeader(HttpRequestBaseHC4 httpRequest, boolean refreshToken) {
        String uri = httpRequest.getURI().toString();
        String resourceId = resourceIdFromUri(uri);

        if (resourceId != null) {
            String accessToken = getAccessToken(resourceId, refreshToken);
            httpRequest.setHeader("Authorization", "Bearer " + accessToken);
        }
    }

    private String resourceIdFromUri(String uri) {
        String resourceId = null;

        if (uri.contains("login")) {
            resourceId = null;
        } else if (uri.contains("office")) {
            resourceId = Constants.OFFICE_RESOURCE_ID;
        } else if (uri.contains("graph.windows")) {
            resourceId = Constants.AAD_RESOURCE_ID;
        } else if (uri.contains("graph.microsoft")) {
            resourceId = Constants.OFFICE_RESOURCE_ID_UNIFIED;
        }
        return resourceId;
    }

    private String getAccessToken(String resourceId, boolean isRefresh) {
        return TokenHandler.getAccessToken(resourceId, isRefresh);
    }

    private void writeHttpLog(String message) {
        if (!mLogDisabled) {
            Date dateTime = Calendar.getInstance().getTime();
            String dateTimeString = DateFmt.toFullDateString(dateTime);
            String timedMessage = String.format("%s %s", dateTimeString, message);

            Manager.Instance.getHttpTracer().writeLine(timedMessage);
        }
    }

    @Override
    protected void traceRequest(HttpRequestBaseHC4 httpRequest, String requestBody) {
        String traceMessage = String.format("%s URI=%s", httpRequest.getMethod(), httpRequest.getURI());

        if (requestBody != null) {
            traceMessage = String.format("%s, BODY=%s", traceMessage, requestBody);
        }

        Log.i("HHHH", traceMessage);
        writeHttpLog(traceMessage);
    }

    @Override
    protected void traceResponse(int statusCode, String data) {
        String traceMessage = String.format("%s", statusCode);

        if (!Utils.isNullOrEmpty(data)) {
            if (statusCode < 300) {
                traceMessage += String.format(" RESPONSE=%s", data);
            } else {
                String errMessage = new RestErrorParser().parse(data);
                handleFailure(statusCode, errMessage);

                traceMessage += String.format(" ERROR=%s", errMessage);
            }
        }

        writeHttpLog(traceMessage);
        Log.i("HHHH:RESPONSE=", traceMessage);
    }

    protected void handleFailure(int statusCode, String errMessage) {
        Log.e("HTTP ERROR", String.format("%s", statusCode));
        ErrorLogger.log(String.format("Http Error: %s\n%s", statusCode, errMessage));

        mErrorMessage = errMessage;
    }

    private boolean needsTokenRefresh(HttpResponse response) {
        StatusLine status = response.getStatusLine();

        if (status.getStatusCode() == 401) {
            return true;
        }
        return false;
    }

    public static boolean isUnified() {
        return mUnified;
    }

    public static void setUnified(boolean unified) {
        mUnified = unified;
    }

    private static String getOfficeEndPoint() {
        return mUnified ? Constants.OFFICE_ENDPOINT_UNIFIED : Constants.OFFICE_ENDPOINT;
    }

    public static String getAADEndPoint() {
        return mUnified ? Constants.AAD_ENDPOINT_UNIFIED : Constants.AAD_ENDPOINT;
    }
}