use of ch.cyberduck.core.DefaultIOExceptionMappingService in project cyberduck by iterate-ch.
the class BoxUploadHelper method commitUploadSession.
public Files commitUploadSession(final Path file, final String uploadSessionId, final TransferStatus overall, final List<UploadPart> uploadParts) throws BackgroundException {
try {
final HttpPost request = new HttpPost(String.format("%s/files/upload_sessions/%s/commit", client.getBasePath(), uploadSessionId));
if (!Checksum.NONE.equals(overall.getChecksum())) {
request.addHeader(new BasicHeader("Digest", String.format("sha=%s", overall.getChecksum().hash)));
}
final ByteArrayOutputStream content = new ByteArrayOutputStream();
final UploadSessionIdCommitBody body = new UploadSessionIdCommitBody().parts(uploadParts);
new JSON().getContext(null).writeValue(content, body);
request.setEntity(new ByteArrayEntity(content.toByteArray()));
if (overall.isExists()) {
if (StringUtils.isNotBlank(overall.getRemote().getETag())) {
request.addHeader(new BasicHeader(HttpHeaders.IF_MATCH, overall.getRemote().getETag()));
} else {
log.warn(String.format("Missing remote attributes in transfer status to read current ETag for %s", file));
}
}
return session.getClient().execute(request, new BoxClientErrorResponseHandler<Files>() {
@Override
public Files handleResponse(final HttpResponse response) throws IOException {
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED) {
if (log.isDebugEnabled()) {
log.debug(String.format("Wait for server to process chunks with response %s", response));
}
this.flush(file, response, uploadSessionId);
return session.getClient().execute(request, this);
}
return super.handleResponse(response);
}
@Override
public Files handleEntity(final HttpEntity entity) throws IOException {
return new JSON().getContext(null).readValue(entity.getContent(), Files.class);
}
/**
* Wait for server processing all pending chunks
*/
private void flush(final Path file, final HttpResponse response, final String uploadSessionId) throws IOException {
UploadSession uploadSession;
do {
final HttpGet request = new HttpGet(String.format("%s/files/upload_sessions/%s", client.getBasePath(), uploadSessionId));
uploadSession = new JSON().getContext(null).readValue(session.getClient().execute(request).getEntity().getContent(), UploadSession.class);
if (log.isDebugEnabled()) {
log.debug(String.format("Server processed %d of %d parts", uploadSession.getNumPartsProcessed(), uploadSession.getTotalParts()));
}
} while (!Objects.equals(uploadSession.getNumPartsProcessed(), uploadSession.getTotalParts()));
}
});
} catch (HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map("Upload {0} failed", e, file);
} catch (IOException e) {
throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file);
}
}
use of ch.cyberduck.core.DefaultIOExceptionMappingService in project cyberduck by iterate-ch.
the class BoxWriteFeature method write.
@Override
public HttpResponseOutputStream<File> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
final DelayedHttpEntityCallable<File> command = new DelayedHttpEntityCallable<File>() {
@Override
public File call(final AbstractHttpEntity entity) throws BackgroundException {
try {
final HttpPost request;
if (status.isExists()) {
request = new HttpPost(String.format("%s/files/%s/content?fields=%s", client.getBasePath(), fileid.getFileId(file, new DisabledListProgressListener()), String.join(",", BoxAttributesFinderFeature.DEFAULT_FIELDS)));
} else {
request = new HttpPost(String.format("%s/files/content?fields=%s", client.getBasePath(), String.join(",", BoxAttributesFinderFeature.DEFAULT_FIELDS)));
}
final Checksum checksum = status.getChecksum();
if (Checksum.NONE != checksum) {
switch(checksum.algorithm) {
case sha1:
request.addHeader(HttpHeaders.CONTENT_MD5, checksum.hash);
}
}
final ByteArrayOutputStream content = new ByteArrayOutputStream();
new JSON().getContext(null).writeValue(content, new FilescontentAttributes().name(file.getName()).parent(new FilescontentAttributesParent().id(fileid.getFileId(file.getParent(), new DisabledListProgressListener()))).contentModifiedAt(status.getTimestamp() != null ? new DateTime(status.getTimestamp()) : null));
final MultipartEntityBuilder multipart = MultipartEntityBuilder.create();
multipart.addBinaryBody("attributes", content.toByteArray());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
entity.writeTo(out);
multipart.addBinaryBody("file", out.toByteArray(), null == status.getMime() ? ContentType.APPLICATION_OCTET_STREAM : ContentType.create(status.getMime()), file.getName());
request.setEntity(multipart.build());
if (status.isExists()) {
if (StringUtils.isNotBlank(status.getRemote().getETag())) {
request.addHeader(new BasicHeader(HttpHeaders.IF_MATCH, status.getRemote().getETag()));
} else {
log.warn(String.format("Missing remote attributes in transfer status to read current ETag for %s", file));
}
}
final Files files = session.getClient().execute(request, new BoxClientErrorResponseHandler<Files>() {
@Override
public Files handleEntity(final HttpEntity entity) throws IOException {
return new JSON().getContext(null).readValue(entity.getContent(), Files.class);
}
});
if (log.isDebugEnabled()) {
log.debug(String.format("Received response %s for upload of %s", files, file));
}
if (files.getEntries().stream().findFirst().isPresent()) {
return files.getEntries().stream().findFirst().get();
}
throw new NotfoundException(file.getAbsolute());
} catch (HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map(e);
} catch (IOException e) {
throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file);
}
}
@Override
public long getContentLength() {
return -1L;
}
};
return this.write(file, status, command);
}
use of ch.cyberduck.core.DefaultIOExceptionMappingService in project cyberduck by iterate-ch.
the class BoxChunkedWriteFeature method write.
@Override
public HttpResponseOutputStream<File> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
final DelayedHttpEntityCallable<File> command = new DelayedHttpEntityCallable<File>() {
@Override
public File call(final AbstractHttpEntity entity) throws BackgroundException {
try {
final HttpRange range = HttpRange.withStatus(new TransferStatus().withLength(status.getLength()).withOffset(status.getOffset()));
final String uploadSessionId = status.getParameters().get(BoxLargeUploadService.UPLOAD_SESSION_ID);
final String overall_length = status.getParameters().get(BoxLargeUploadService.OVERALL_LENGTH);
if (log.isDebugEnabled()) {
log.debug(String.format("Send range %s for file %s", range, file));
}
final HttpPut request = new HttpPut(String.format("%s/files/upload_sessions/%s", client.getBasePath(), uploadSessionId));
// Must not overlap with the range of a part already uploaded this session.
request.addHeader(new BasicHeader(HttpHeaders.CONTENT_RANGE, String.format("bytes %d-%d/%d", range.getStart(), range.getEnd(), Long.valueOf(overall_length))));
request.addHeader(new BasicHeader("Digest", String.format("sha=%s", status.getChecksum())));
request.setEntity(entity);
final UploadedPart uploadedPart = session.getClient().execute(request, new BoxClientErrorResponseHandler<UploadedPart>() {
@Override
public UploadedPart handleEntity(final HttpEntity entity1) throws IOException {
return new JSON().getContext(null).readValue(entity1.getContent(), UploadedPart.class);
}
});
if (log.isDebugEnabled()) {
log.debug(String.format("Received response %s for upload of %s", uploadedPart, file));
}
return new File().size(status.getLength()).sha1(uploadedPart.getPart().getSha1());
} catch (HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map(e);
} catch (IOException e) {
throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file);
}
}
@Override
public long getContentLength() {
return -1L;
}
};
return this.write(file, status, command);
}
use of ch.cyberduck.core.DefaultIOExceptionMappingService in project cyberduck by iterate-ch.
the class BoxListService method list.
protected AttributedList<Path> list(final Path directory, final ListProgressListener listener, final int chunksize) throws BackgroundException {
try {
final AttributedList<Path> list = new AttributedList<>();
int offset = 0;
Items items;
do {
items = new FoldersApi(new BoxApiClient(session.getClient())).getFoldersIdItems(directory.isRoot() ? "0" : fileid.getFileId(directory, listener), BoxAttributesFinderFeature.DEFAULT_FIELDS, false, null, (long) offset, (long) chunksize, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY);
for (Object entry : items.getEntries()) {
if (!(entry instanceof Map)) {
log.error(String.format("Unexpected entry %s", entry));
continue;
}
final Object type = ((Map) entry).get("type");
if (!(type instanceof String)) {
log.error(String.format("Missing type %s", type));
continue;
}
switch(type.toString()) {
case "file":
final File file = new JSON().getContext(null).readValue(new JSON().getContext(null).writeValueAsString(entry), File.class);
list.add(new Path(directory, file.getName(), EnumSet.of(Path.Type.file), attributes.toAttributes(file)));
break;
case "folder":
final Folder folder = new JSON().getContext(null).readValue(new JSON().getContext(null).writeValueAsString(entry), Folder.class);
list.add(new Path(directory, folder.getName(), EnumSet.of(Path.Type.directory), attributes.toAttributes(folder)));
break;
}
listener.chunk(directory, list);
}
offset += chunksize;
} while (items.getEntries().size() == chunksize);
return list;
} catch (ApiException e) {
throw new BoxExceptionMappingService(fileid).map("Listing directory {0} failed", e, directory);
} catch (JsonProcessingException e) {
throw new DefaultIOExceptionMappingService().map("Listing directory {0} failed", e, directory);
}
}
use of ch.cyberduck.core.DefaultIOExceptionMappingService in project cyberduck by iterate-ch.
the class BrickWriteFeature method write.
@Override
public HttpResponseOutputStream<FileEntity> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException {
final String uploadUri;
FileUploadPartEntity uploadPartEntity = null;
if (StringUtils.isBlank(status.getUrl())) {
uploadPartEntity = new BrickUploadFeature(session, this).startUpload(file);
uploadUri = uploadPartEntity.getUploadUri();
} else {
uploadUri = status.getUrl();
}
final HttpResponseOutputStream<FileEntity> stream = this.write(file, status, new DelayedHttpEntityCallable<FileEntity>() {
@Override
public FileEntity call(final AbstractHttpEntity entity) throws BackgroundException {
try {
final HttpPut request = new HttpPut(uploadUri);
request.setEntity(entity);
request.setHeader(HttpHeaders.CONTENT_TYPE, MimeTypeService.DEFAULT_CONTENT_TYPE);
final HttpResponse response = session.getClient().execute(request);
// Validate response
try {
switch(response.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
// Upload complete
if (response.containsHeader("ETag")) {
if (log.isInfoEnabled()) {
log.info(String.format("Received response %s for part number %d", response, status.getPart()));
}
if (HashAlgorithm.md5.equals(status.getChecksum().algorithm)) {
final Checksum etag = Checksum.parse(StringUtils.remove(response.getFirstHeader("ETag").getValue(), '"'));
if (!status.getChecksum().equals(etag)) {
throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()), MessageFormat.format("Mismatch between {0} hash {1} of uploaded data and ETag {2} returned by the server", etag.algorithm.toString(), status.getChecksum().hash, etag.hash));
}
}
return null;
} else {
log.error(String.format("Missing ETag in response %s", response));
throw new InteroperabilityException(response.getStatusLine().getReasonPhrase());
}
default:
EntityUtils.updateEntity(response, new BufferedHttpEntity(response.getEntity()));
throw new DefaultHttpResponseExceptionMappingService().map(new HttpResponseException(response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase()));
}
} finally {
EntityUtils.consume(response.getEntity());
}
} catch (HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map(e);
} catch (IOException e) {
throw new DefaultIOExceptionMappingService().map(e);
}
}
@Override
public long getContentLength() {
return status.getLength();
}
});
if (StringUtils.isBlank(status.getUrl())) {
final String ref = uploadPartEntity.getRef();
return new HttpResponseOutputStream<FileEntity>(new ProxyOutputStream(stream), new BrickAttributesFinderFeature(session), status) {
private final AtomicBoolean close = new AtomicBoolean();
@Override
public FileEntity getStatus() throws BackgroundException {
return stream.getStatus();
}
@Override
public void close() throws IOException {
if (close.get()) {
log.warn(String.format("Skip double close of stream %s", this));
return;
}
super.close();
try {
new BrickUploadFeature(session, BrickWriteFeature.this).completeUpload(file, ref, status, Collections.singletonList(status));
} catch (BackgroundException e) {
throw new IOException(e.getMessage(), e);
} finally {
close.set(true);
}
}
};
}
return stream;
}
Aggregations