All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.portlek.sfs.WeedFSClientImpl Maven / Gradle / Ivy

There is a newer version: 5.7
Show newest version
/*
 * (C) Copyright 2013 Scoop IT SAS (http://scoop.it/) and others.
 *
 * 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.
 *
 * Contributors:
 *     Philippe GASSMANN
 *     Jean-Baptiste BELLET
 */
package io.github.portlek.sfs;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.portlek.sfs.caching.LookupCache;
import io.github.portlek.sfs.net.AssignResult;
import io.github.portlek.sfs.net.LookupResult;
import io.github.portlek.sfs.net.WriteResult;
import io.github.portlek.sfs.status.MasterStatus;
import io.github.portlek.sfs.status.VolumeStatus;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;

class WeedFSClientImpl implements WeedFSClient {

    final URL masterURL;

    final HttpClient httpClient;

    final LookupCache lookupCache;

    WeedFSClientImpl(final URL masterURL, final HttpClient httpClient, final LookupCache lookupCache) {
        this.masterURL = masterURL;
        this.httpClient = httpClient;
        this.lookupCache = lookupCache;
    }

    @Override
    public Assignation assign(final AssignParams params) throws IOException {
        final StringBuilder url = new StringBuilder(new URL(this.masterURL, "/dir/assign").toExternalForm());
        url.append("?count=");
        url.append(params.versionCount);
        if (params.replicationStrategy != null) {
            url.append("&replication=");
            url.append(params.replicationStrategy.parameterValue);
        }

        if (params.collection != null) {
            url.append("&collection=");
            url.append(params.collection);
        }

        final HttpGet get = new HttpGet(url.toString());
        try {
            final HttpResponse response = this.httpClient.execute(get);
            final ObjectMapper mapper = new ObjectMapper();

            System.out.println(response.toString());
            try {
                final InputStream content = response.getEntity().getContent();
                final AssignResult result = mapper.readValue(content, AssignResult.class);

                if (result.error != null) {
                    throw new WeedFSException(result.error);
                }

                return new Assignation(result);
            } catch (final JsonMappingException | JsonParseException e) {
                throw new WeedFSException("Unable to parse JSON from weed-fs", e);
            }
        } finally {
            get.abort();
        }
    }

    @Override
    public int write(final WeedFSFile file, final Location location, final File fileToUpload) throws IOException {
        if (fileToUpload.length() == 0) {
            throw new WeedFSException("Cannot write a 0-length file");
        }
        return this.write(file, location, fileToUpload, null, null, null);
    }

    @Override
    public int write(final WeedFSFile file, final Location location, final byte[] dataToUpload, final String fileName) throws IOException {
        if (dataToUpload.length == 0) {
            throw new WeedFSException("Cannot write a 0-length data");
        }
        return this.write(file, location, null, dataToUpload, null, fileName);
    }

    @Override
    public int write(final WeedFSFile file, final Location location, final InputStream inputToUpload, final String fileName) throws IOException {
        return this.write(file, location, null, null, inputToUpload, fileName);
    }

    @Override
    public void delete(final WeedFSFile file, final Location location) throws IOException {
        final StringBuilder url = new StringBuilder();
        if (!location.publicUrl.contains("http")) {
            url.append("http://");
        }
        url.append(location.publicUrl);
        url.append("/");
        url.append(file.fid);

        final HttpDelete delete = new HttpDelete(url.toString());
        try {
            final HttpResponse response = this.httpClient.execute(delete);

            final StatusLine line = response.getStatusLine();
            if (line.getStatusCode() < 200 || line.getStatusCode() > 299) {
                throw new WeedFSException("Error deleting file " + file.fid + " on " + location.publicUrl + ": " + line.getStatusCode() + " "
                    + line.getReasonPhrase());
            }
        } finally {
            delete.abort();
        }
    }

    @Override
    public List lookup(final long volumeId) throws IOException {
        if (this.lookupCache != null) {
            final List ret = this.lookupCache.lookup(volumeId);
            if (ret != null) {
                return ret;
            }
        }

        final StringBuilder url = new StringBuilder(new URL(this.masterURL, "/dir/lookup").toExternalForm());
        url.append("?volumeId=");
        url.append(volumeId);

        final HttpGet get = new HttpGet(url.toString());
        try {
            final HttpResponse response = this.httpClient.execute(get);

            final ObjectMapper mapper = new ObjectMapper();
            try {
                final LookupResult result = mapper.readValue(response.getEntity().getContent(), LookupResult.class);

                if (result.error != null) {
                    throw new WeedFSException(result.error);
                }

                if (this.lookupCache != null && result.locations != null && result.locations.size() > 0) {
                    this.lookupCache.setLocation(volumeId, result.locations);
                }

                return result.locations;
            } catch (final JsonMappingException | JsonParseException e) {
                throw new WeedFSException("Unable to parse JSON from weed-fs", e);
            }
        } finally {
            get.abort();
        }

    }

    @Override
    public boolean exist(final WeedFSFile file, final Location location) throws IOException {
        final StringBuilder url = new StringBuilder();
        if (!location.publicUrl.contains("http")) {
            url.append("http://");
        }
        url.append(location.publicUrl);
        url.append('/');
        url.append(file.fid);

        if (file.version > 0) {
            url.append('_');
            url.append(file.version);
        }
        return this.httpClient
            .execute(new HttpGet(url.toString()))
            .getStatusLine()
            .getStatusCode() != 404;
    }

    @Override
    public InputStream read(final WeedFSFile file, final Location location) throws IOException {
        final StringBuilder url = new StringBuilder();
        if (!location.publicUrl.contains("http")) {
            url.append("http://");
        }
        url.append(location.publicUrl);
        url.append('/');
        url.append(file.fid);

        if (file.version > 0) {
            url.append('_');
            url.append(file.version);
        }
        final HttpGet get = new HttpGet(url.toString());
        final HttpResponse response = this.httpClient.execute(get);
        final StatusLine line = response.getStatusLine();
        if (line.getStatusCode() == 404) {
            get.abort();
            throw new WeedFSFileNotFoundException(file, location);
        }
        if (line.getStatusCode() != 200) {
            get.abort();
            throw new WeedFSException("Error reading file " + file.fid + " on " + location.publicUrl + ": " + line.getStatusCode() + " "
                + line.getReasonPhrase());
        }
        return response.getEntity().getContent();
    }

    @Override
    public MasterStatus getMasterStatus() throws IOException {
        final URL url = new URL(this.masterURL, "/dir/status");

        final HttpGet get = new HttpGet(url.toString());

        try {
            final HttpResponse response = this.httpClient.execute(get);
            final StatusLine line = response.getStatusLine();

            if (line.getStatusCode() != 200) {
                throw new IOException("Not 200 status recieved for master status url: " + url.toExternalForm());
            }

            final ObjectMapper mapper = new ObjectMapper();
            try {
                return mapper.readValue(response.getEntity().getContent(), MasterStatus.class);
            } catch (final JsonMappingException | JsonParseException e) {
                throw new WeedFSException("Unable to parse JSON from weed-fs", e);
            }
        } finally {
            get.abort();
        }
    }

    @Override
    public VolumeStatus getVolumeStatus(final Location location) throws IOException {
        final StringBuilder url = new StringBuilder();
        if (!location.publicUrl.contains("http")) {
            url.append("http://");
        }
        url.append(location.publicUrl);
        url.append("/status");

        final HttpGet get = new HttpGet(url.toString());

        try {
            final HttpResponse response = this.httpClient.execute(get);
            final StatusLine line = response.getStatusLine();

            if (line.getStatusCode() != 200) {
                throw new IOException("Not 200 status recieved for master status url: " + url.toString());
            }

            final ObjectMapper mapper = new ObjectMapper();
            try {

                return mapper.readValue(response.getEntity().getContent(), VolumeStatus.class);

            } catch (final JsonMappingException | JsonParseException e) {
                throw new WeedFSException("Unable to parse JSON from weed-fs", e);
            }
        } finally {
            get.abort();
        }
    }

    private String sanitizeFileName(final String fileName) {
        if (StringUtils.isBlank(fileName)) {
            return "file";
        } else if (fileName.length() > 256) {
            return fileName.substring(0, 255);
        }
        return fileName;

    }

    private int write(final WeedFSFile file, final Location location, final File fileToUpload, final byte[] dataToUpload, final InputStream inputToUpload, String fileName)
        throws IOException {
        final StringBuilder url = new StringBuilder();
        if (!location.publicUrl.contains("http")) {
            url.append("http://");
        }
        url.append(location.publicUrl);
        url.append('/');
        url.append(file.fid);

        if (file.version > 0) {
            url.append('_');
            url.append(file.version);
        }

        final HttpPost post = new HttpPost(url.toString());

        final MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
        if (fileToUpload != null) {
            if (fileName == null) {
                fileName = fileToUpload.getName();
            }
            multipartEntityBuilder.addBinaryBody("file", fileToUpload, ContentType.APPLICATION_OCTET_STREAM, this.sanitizeFileName(fileName));
        } else if (dataToUpload != null) {
            multipartEntityBuilder.addBinaryBody("file", dataToUpload, ContentType.APPLICATION_OCTET_STREAM, this.sanitizeFileName(fileName));
        } else {
            multipartEntityBuilder.addBinaryBody("file", inputToUpload, ContentType.APPLICATION_OCTET_STREAM, this.sanitizeFileName(fileName));
        }
        post.setEntity(multipartEntityBuilder.build());

        try {
            final HttpResponse response = this.httpClient.execute(post);
            final ObjectMapper mapper = new ObjectMapper();
            try {
                final InputStream content = response.getEntity().getContent();
                final WriteResult result = mapper.readValue(content, WriteResult.class);

                if (result.error != null) {
                    throw new WeedFSException(result.error);
                }

                return result.size;
            } catch (final JsonMappingException | JsonParseException e) {
                throw new WeedFSException("Unable to parse JSON from weed-fs", e);
            }
        } finally {
            post.abort();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy