Package io.fathom.cloud.openstack.client.storage

Source Code of io.fathom.cloud.openstack.client.storage.OpenstackStorageClient

package io.fathom.cloud.openstack.client.storage;

import io.fathom.cloud.openstack.client.OpenstackServiceClientBase;
import io.fathom.cloud.openstack.client.RestClientException;
import io.fathom.cloud.openstack.client.identity.TokenProvider;
import io.fathom.cloud.openstack.client.storage.model.StorageListChunk;
import io.fathom.cloud.openstack.client.storage.model.StorageObjectInfo;
import io.fathom.http.HttpClient;
import io.fathom.http.HttpRequest;
import io.fathom.http.HttpResponse;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.google.common.net.HttpHeaders;

public class OpenstackStorageClient extends OpenstackServiceClientBase {
    public static final String SERVICE_TYPE = "object-store";

    public static abstract class GetFileOption {

        public abstract void modifyRequest(HttpRequest request);
    }

    public static class Range extends GetFileOption {

        private final Long from;
        private final Long to;

        public Range(Long from, Long to) {
            if (from == null && to == null) {
                throw new IllegalArgumentException();
            }

            this.from = from;
            this.to = to;
        }

        @Override
        public void modifyRequest(HttpRequest request) {
            // Note than -123 means the last 123 bytes in a range header, so we
            // want 0-123
            if ((from == null || from == 0) && to == null) {
                return;
            }

            StringBuilder sb = new StringBuilder();
            sb.append("bytes=");
            if (from != null) {
                sb.append(from);
            }
            sb.append('-');
            if (to != null) {
                sb.append(to);
            }

            request.setHeader("Range", sb.toString());
        }

    }

    private static final Logger log = LoggerFactory.getLogger(OpenstackStorageClient.class);

    public OpenstackStorageClient(HttpClient httpClient, URI uri, TokenProvider tokenProvider) {
        super(httpClient, uri, tokenProvider);
    }

    public StorageObjectInfo findStorageObjectInfo(String path) throws RestClientException {
        HttpRequest request = buildHead(path);
        HttpResponse response = null;
        try {
            response = executeRawRequest(request);

            StorageObjectInfo info = new StorageObjectInfo();

            {
                String header = response.getFirstHeader(HttpHeaders.CONTENT_LENGTH);
                if (header != null) {
                    info.length = Long.valueOf(header);
                }
            }

            {
                String header = response.getFirstHeader(HttpHeaders.LAST_MODIFIED);
                if (header != null) {
                    info.lastModified = new Date(header);
                }
            }

            return info;
        } catch (RestClientException e) {
            if (e.is(404)) {
                return null;
            }
            throw e;
        } finally {
            closeQuietly(response);
        }
    }

    public void putFile(String path, File src) throws RestClientException {
        HttpRequest request = buildPut(path);

        ByteSource entity = Files.asByteSource(src);
        setRequestContent(request, entity);

        doByteArrayRequest(request);
    }

    public void appendToFile(String path, ByteSource entity) throws RestClientException {
        HttpRequest request = buildPost(path);
        setRequestContent(request, entity);

        doByteArrayRequest(request);
    }

    public void putFile(String path, ByteSource entity) throws RestClientException {
        // TODO: Support metadata
        HttpRequest request = buildPut(path);
        setRequestContent(request, entity);

        doByteArrayRequest(request);
    }

    public void delete(String path) throws RestClientException {
        HttpRequest request = buildDelete(path);
        doStringRequest(request);
    }

    public StorageListChunk listObjectsChunked(String bucket, String prefix, String delimiter, int maxListingLength,
            String priorLastKey) throws RestClientException {
        String relativeUri = bucket + "?format=json";
        if (prefix != null) {
            relativeUri += "&prefix=" + urlEscape(prefix);
        }
        if (delimiter != null) {
            relativeUri += "&delimiter=" + urlEscape(delimiter);
        }
        if (priorLastKey != null) {
            throw new UnsupportedOperationException();
        }
        if (maxListingLength != 0) {
            relativeUri += "&limit=" + maxListingLength;
        }
        HttpRequest get = buildGet(relativeUri);
        List<StorageObjectInfo> objects = doListRequest(get, StorageObjectInfo.class);

        String nextKey = null;
        if (maxListingLength != 0 && objects.size() == maxListingLength) {
            // set nextKey
            throw new UnsupportedOperationException();
        }

        List<String> subdirs = new ArrayList<String>();
        List<StorageObjectInfo> files = new ArrayList<StorageObjectInfo>();

        for (StorageObjectInfo object : objects) {
            if (object.subdir == null) {
                files.add(object);
            } else {
                subdirs.add(object.subdir);
            }
        }
        return new StorageListChunk(objects, subdirs, nextKey);
    }

    public StorageObject getObject(String path, GetFileOption... options) throws RestClientException {
        return getObject(path, Arrays.asList(options));
    }

    public StorageObject getObject(String path, List<GetFileOption> options) throws RestClientException {
        HttpRequest request = buildGet(path);

        for (GetFileOption option : options) {
            option.modifyRequest(request);
        }

        HttpResponse response = null;
        try {
            response = executeRawRequest(request);

            InputStream is;
            try {
                is = response.getInputStream();
            } catch (IOException e) {
                throw new RestClientException("Error reading response", e);
            }
            if (is == null) {
                throw new IllegalStateException();
            }

            is = new CloseHttpInputStream(is, response);

            StorageObject object = new StorageObject(is);
            response = null; // Don't close

            return object;
        } catch (RestClientException e) {
            if (e.is(404)) {
                return null;
            }
            throw e;
        } finally {
            closeQuietly(response);
        }
    }

    @Override
    protected boolean shouldRetry(int attempt, int statusCode) {
        if (attempt == 1 && statusCode == 401) {
            tokenProvider.reset();
            return true;
        }
        return false;
    }

    public List<StorageObjectInfo> listChildren(String bucket, String prefix, String delimiter)
            throws RestClientException {
        List<StorageObjectInfo> ret = new ArrayList<StorageObjectInfo>();

        int maxListingLength = 2000;

        try {
            String marker = null;
            while (true) {
                StorageListChunk chunk = listObjectsChunked(bucket, prefix, delimiter, maxListingLength, marker);
                for (StorageObjectInfo o : chunk.getObjects()) {
                    ret.add(o);
                }
                marker = chunk.getPriorLastKey();
                if (marker == null) {
                    break;
                }
            }
        } catch (RestClientException e) {
            if (ret.isEmpty() && e.is(404)) {
                return null;
            }
            throw new RestClientException("Error listing children", e);
        }
        return ret;
    }

    public void createBucket(String bucket) throws RestClientException {
        HttpRequest request = buildPost(bucket);
        doStringRequest(request);
    }

}
TOP

Related Classes of io.fathom.cloud.openstack.client.storage.OpenstackStorageClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.