private static void makeSingleCall()

in src/main/java/com/microsoft/azure/datalake/store/HttpTransport.java [156:349]


    private static void makeSingleCall(ADLStoreClient client,
                                       Operation op,
                                       String path,
                                       QueryParams queryParams,
                                       byte[] requestBody,
                                       int offsetWithinContentsArray,
                                       int length,
                                       RequestOptions opts,
                                       OperationResponse resp) {

        if (client == null) throw new IllegalArgumentException("client is null");
        if (client.getAccountName() == null || client.getAccountName().equals("")) {
            resp.successful = false;
            resp.message = "Account name or client is null or blank";
            return;
        }

        String token = null;
        long tokenStartTime = System.nanoTime();
        try {
            token = client.getAccessToken();
            if (token == null || token.equals("")) {
                resp.successful = false;
                resp.message = "Access token is null or blank";
                resp.tokenAcquisitionLatency = System.nanoTime() - tokenStartTime;
                return;
            }
        } catch (IOException ex) {
            resp.successful = false;
            resp.message = "Error fetching access token";
            resp.ex = ex;
            resp.tokenAcquisitionLatency = System.nanoTime() - tokenStartTime;
            return;
        }
        resp.tokenAcquisitionLatency = System.nanoTime() - tokenStartTime;

        if (op == null) {
            resp.successful = false;
            resp.message = "operation is null";
            return;
        }

        if (path == null || path.trim().equals("")) {
            resp.successful = false;
            resp.message = "path is null";
            return;
        }

        resp.opCode = op.name;

        if (requestBody != null && requestBody.length > 0) {
            if (offsetWithinContentsArray < 0 ||
                    length < 0 ||
                    offsetWithinContentsArray + length < 0 || // integer overflow
                    offsetWithinContentsArray >= requestBody.length ||
                    offsetWithinContentsArray + length > requestBody.length) {
                throw new IndexOutOfBoundsException("offset+length overflows byte buffer for path " + path);
            }
        } else {
            if (offsetWithinContentsArray != 0 || length != 0) {
                throw new IndexOutOfBoundsException("Non-zero offset or length with null body for path " + path);
            }
        }


        // Build URL
        StringBuilder urlString = new StringBuilder();
        urlString.append(client.getHttpPrefix());    // http or https
        urlString.append("://");
        urlString.append(client.getAccountName());
        urlString.append(op.namespace);

        String prefix = client.getFilePathPrefix();
        if (prefix != null) urlString.append(prefix);

        if (path.charAt(0) != '/') urlString.append('/');
        try {
            urlString.append((new URI(null, null, path, null)).toASCIIString());   // use URI to encode path
        } catch (URISyntaxException ex) {
            resp.successful = false;
            resp.message = "Invalid path " + path;
            return;
        }
        urlString.append('?');
        urlString.append(queryParams.serialize());

        URL url;
        try {
            url = new URL(urlString.toString());
        } catch (MalformedURLException ex) {
            resp.ex = ex;
            resp.successful = false;
            return;
        }

        HttpURLConnection conn = null;
        String userAgent = client.getUserAgent();
        try {
            conn = (HttpURLConnection) url.openConnection();
            if(conn instanceof HttpsURLConnection && client.shouldAlterCipherSuits()) {
                HttpsURLConnection secureConn = (HttpsURLConnection) conn;
                SSLSocketFactoryEx sslSocketFactoryEx = null;
                try {
                    sslSocketFactoryEx =
                        SSLSocketFactoryEx.getDefaultFactory(client.getSSLChannelMode());
                } catch (IOException e) {
                    // Suppress exception. Failure to init SSLSocketFactoryEx would have only performance impact.
                    log.info("Failed to init SSLSocketFactoryEx, Fallback to default SSLSocketFactory");
                }

                if(sslSocketFactoryEx != null) {
                    secureConn.setSSLSocketFactory(sslSocketFactoryEx);
                    userAgent += "/" + sslSocketFactoryEx.getUserAgent();
                }
            }

            // Setup Http Request (method and headers)
            conn.setRequestProperty("Authorization", token);
            conn.setRequestProperty("User-Agent", userAgent);
            conn.setRequestProperty("x-ms-client-request-id", opts.requestid);
            String latencyHeader = LatencyTracker.get();
            if (latencyHeader != null) conn.setRequestProperty("x-ms-adl-client-latency", latencyHeader);
            if (client.getTiHeaderValue() != null)
                conn.setRequestProperty("x-ms-tracking-info", client.getTiHeaderValue());
            conn.setConnectTimeout(opts.timeout);
            conn.setReadTimeout(opts.timeout);
            conn.setUseCaches(false);
            conn.setRequestMethod(op.method);
            conn.setDoInput(true);
            if(op.enforceMimeTypeJson) {
                conn.setRequestProperty("Content-Type", "application/json");
            }

            // populate request body if applicable
            if (!op.method.equals("GET")) {
                conn.setDoOutput(true);
                conn.setRequestMethod(op.method);
                OutputStream outStr = conn.getOutputStream();
                if (op.requiresBody && requestBody != null) {
                    outStr.write(requestBody, offsetWithinContentsArray, length);
                    outStr.close();
                } else {
                    // server *requires* a Content-Length header, and doesnt take absence of header as 0 (bad behavior)
                    // The only way to force java to send "Content-Length:0" is to do this.
                    // Setting Content-Length header to 0 using setRequestProprty doesnt work (bad behavior)
                    byte[] buf = new byte[]{};  // zero-length byte-array
                    outStr.write(buf);
                    outStr.close();
                }
            }

            // get Response Stream if applicable
            resp.httpResponseCode = conn.getResponseCode();
            resp.httpResponseMessage = conn.getResponseMessage();
            resp.requestId = conn.getHeaderField("x-ms-request-id");
            resp.responseContentLength = conn.getHeaderFieldLong("Content-Length", 0);
            String chunked = conn.getHeaderField("Transfer-Encoding");
            if (chunked != null && chunked.equals("chunked")) resp.responseChunked = true;

            // if request failed, then the body of an HTTP 4xx or 5xx response contains error info as JSon
            if (resp.httpResponseCode >= 400) {
                if (resp.httpResponseCode == 401 && tokenlog.isDebugEnabled()) {  // log auth token errors separately
                    String logline = "HTTPRequest,HTTP401,cReqId:" +
                            opts.requestid + ",sReqId:" +
                            resp.requestId + ",path:" +
                            path + ",token:" +
                            token;             // ok to log, since token doesn't seem to be working anyway
                    tokenlog.debug(logline);
                }
                if (resp.responseContentLength > 0 && conn.getErrorStream() != null) {
                    getCodesFromJSon(conn.getErrorStream(), resp);
                    return;
                }
            } else {
                consumeInputStream(conn.getErrorStream());  // read(ignore) and close if the stream exists
                if (op.returnsBody) {  // response stream will be handled by caller
                    resp.responseStream = conn.getInputStream();
                } else {    // read and discard response stream so it is consumed and connection can be reused
                    consumeInputStream(conn.getInputStream());
                }
            }
        } catch (IOException ex) {
            resp.ex = ex;
            resp.successful = false;
            if (conn != null) {
                try {
                    consumeInputStream(conn.getInputStream());  // read(ignore) and close if the stream exists
                    consumeInputStream(conn.getErrorStream());  // read(ignore) and close if the stream exists
                } catch (IOException ex2) {
                    // ignore, since we already have the root IOException - this part is just when cleaning up error stream
                }
            }
        }
    }