com.ibm.stocator.fs.swift.SwiftAPIDirect.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.stocator.fs.swift.SwiftAPIDirect.java

Source

/**
 * (C) Copyright IBM Corp. 2015, 2016
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.ibm.stocator.fs.swift;

import java.io.IOException;

import org.apache.hadoop.fs.Path;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ibm.stocator.fs.common.Constants;
import com.ibm.stocator.fs.common.Tuple;
import com.ibm.stocator.fs.swift.auth.JossAccount;
import com.ibm.stocator.fs.swift.http.SwiftConnectionManager;

/**
 * Direct client to the object store implementing Swift API
 * This class bypass JOSS library and uses JOSS only to obtain access token and authenticated url
 */
public class SwiftAPIDirect {

    /*
     * Logger
     */
    private static final Logger LOG = LoggerFactory.getLogger(SwiftAPIDirect.class);

    /**
     * Get object
     *
     * @param path path to object
     * @param account Joss account wrapper object
     * @param scm Swift connection manager
     * @return SwiftGETResponse input stream and content length
     * @throws IOException if network issues
     */
    public static SwiftInputStreamWrapper getObject(Path path, JossAccount account, SwiftConnectionManager scm)
            throws IOException {
        return getObject(path, account, 0, 0, scm);
    }

    /**
     * GET object
     *
     * @param path path to the object
     * @param account Joss Account wrapper object
     * @param bytesFrom from from
     * @param bytesTo bytes to
     * @param scm Swift Connection manager
     * @return SwiftInputStreamWrapper that includes input stream and length
     * @throws IOException if network errors
     */
    public static SwiftInputStreamWrapper getObject(Path path, JossAccount account, long bytesFrom, long bytesTo,
            SwiftConnectionManager scm) throws IOException {
        Tuple<Integer, Tuple<HttpRequestBase, HttpResponse>> resp = httpGET(path.toString(), bytesFrom, bytesTo,
                account, scm);
        if (resp.x.intValue() >= 400) {
            LOG.warn("Re-authentication attempt for GET {}", path.toString());
            account.authenticate();
            resp = httpGET(path.toString(), bytesFrom, bytesTo, account, scm);
        }

        SwiftInputStreamWrapper httpStream = new SwiftInputStreamWrapper(resp.y.y.getEntity(), resp.y.x);
        return httpStream;
    }

    /**
     * @param path path to object
     * @param bytesFrom from bytes
     * @param bytesTo to bytes
     * @param account JOSS Account object
     * @return Tuple with HTTP response method and HttpRequestBase HttpResponse
     * @throws IOException if error
     */
    private static Tuple<Integer, Tuple<HttpRequestBase, HttpResponse>> httpGET(String path, long bytesFrom,
            long bytesTo, JossAccount account, SwiftConnectionManager scm) throws IOException {
        LOG.debug("HTTP GET {} request. From {}, To {}", path, bytesFrom, bytesTo);
        HttpGet httpGet = new HttpGet(path);
        httpGet.addHeader("X-Auth-Token", account.getAuthToken());
        if (bytesTo > 0) {
            final String rangeValue = String.format("bytes=%d-%d", bytesFrom, bytesTo);
            httpGet.addHeader(Constants.RANGES_HTTP_HEADER, rangeValue);
        }
        httpGet.addHeader(Constants.USER_AGENT_HTTP_HEADER, Constants.STOCATOR_USER_AGENT);
        CloseableHttpClient httpclient = scm.createHttpConnection();
        CloseableHttpResponse response = httpclient.execute(httpGet);
        int responseCode = response.getStatusLine().getStatusCode();
        LOG.debug("HTTP GET {} response. Status code {}", path, responseCode);
        Tuple<HttpRequestBase, HttpResponse> respData = new Tuple<HttpRequestBase, HttpResponse>(httpGet, response);
        return new Tuple<Integer, Tuple<HttpRequestBase, HttpResponse>>(Integer.valueOf(responseCode), respData);
    }

    /*
     * Sends a HEAD request to get an object's length
     */
    public static long getTempUrlObjectLength(Path path, SwiftConnectionManager scm) throws IOException {

        HttpHead head = new HttpHead(path.toString().replace("swift2d", "https"));
        CloseableHttpResponse response = scm.createHttpConnection().execute(head);
        return Long.parseLong(response.getFirstHeader("Content-Length").getValue());
    }

}