io.github.portlek.sfs.WeedFSClientImpl Maven / Gradle / Ivy
/*
* (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