@Test public void testWrite() throws Exception { final Path bucket = new Path("test-cyberduck", EnumSet.of(Path.Type.directory, Path.Type.volume)); final Path test = new Path(bucket, UUID.randomUUID().toString(), EnumSet.of(Path.Type.file)); final TransferStatus status = new TransferStatus(); final byte[] content = "test".getBytes(StandardCharsets.UTF_8); status.setLength(content.length); status.setChecksum(new SHA1ChecksumCompute().compute(new ByteArrayInputStream(content), status)); status.setTimestamp(1503654614004L); final B2FileidProvider fileid = new B2FileidProvider(session).withCache(cache); final OutputStream out = new B2WriteFeature(session, fileid).write(test, status, new DisabledConnectionCallback()); assertNotNull(out); new StreamCopier(new TransferStatus(), new TransferStatus()).transfer(new ByteArrayInputStream(content), out); out.close(); test.attributes().setVersionId(fileid.getFileid(test, new DisabledListProgressListener())); assertTrue(new B2FindFeature(session, fileid).find(test)); final PathAttributes attributes = new B2ListService(session, fileid).list(test.getParent(), new DisabledListProgressListener()).get(test).attributes(); assertEquals(content.length, attributes.getSize()); final Write.Append append = new B2WriteFeature(session, fileid).append(test, status.getLength(), PathCache.empty()); assertTrue(append.override); assertEquals(content.length, append.size, 0L); final byte[] buffer = new byte[content.length]; final InputStream in = new B2ReadFeature(session, fileid).read(test, new TransferStatus(), new DisabledConnectionCallback()); IOUtils.readFully(in, buffer); in.close(); assertArrayEquals(content, buffer); assertEquals(1503654614004L, new B2AttributesFinderFeature(session, fileid).find(test).getModificationDate()); new B2DeleteFeature(session, fileid).delete(Collections.singletonList(test), new DisabledLoginCallback(), new Delete.DisabledCallback()); }
@Override public HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException { final DelayedHttpEntityCallable<BaseB2Response> command = new DelayedHttpEntityCallable<BaseB2Response>() { @Override public BaseB2Response call(final AbstractHttpEntity entity) throws BackgroundException { try { final Checksum checksum = status.getChecksum(); if(status.isSegment()) { final B2GetUploadPartUrlResponse uploadUrl = session.getClient().getUploadPartUrl(status.getVersion().id); return session.getClient().uploadLargeFilePart(uploadUrl, status.getPart(), entity, checksum.hash); } else { if(null == urls.get()) { final B2GetUploadUrlResponse uploadUrl = session.getClient().getUploadUrl(fileid.getFileid(containerService.getContainer(file), new DisabledListProgressListener())); if(log.isDebugEnabled()) { log.debug(String.format("Obtained upload URL %s for file %s", uploadUrl, file)); } urls.set(uploadUrl); return this.upload(uploadUrl, entity, checksum); } else { final B2GetUploadUrlResponse uploadUrl = urls.get(); if(log.isDebugEnabled()) { log.debug(String.format("Use cached upload URL %s for file %s", uploadUrl, file)); } try { return this.upload(uploadUrl, entity, checksum); } catch(IOException | B2ApiException e) { log.warn(String.format("Remove cached upload URL after failure %s", e)); urls.remove(); return this.upload(uploadUrl, entity, checksum); } } } } catch(B2ApiException e) { throw new B2ExceptionMappingService().map("Upload {0} failed", e, file); } catch(IOException e) { throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file); } } protected BaseB2Response upload(final B2GetUploadUrlResponse uploadUrl, final AbstractHttpEntity entity, final Checksum checksum) throws B2ApiException, IOException, BackgroundException { final Map<String, String> fileinfo = new HashMap<>(status.getMetadata()); if(null != status.getTimestamp()) { fileinfo.put(X_BZ_INFO_SRC_LAST_MODIFIED_MILLIS, String.valueOf(status.getTimestamp())); } return session.getClient().uploadFile(uploadUrl, containerService.getKey(file), entity, checksum.algorithm == HashAlgorithm.sha1 ? checksum.hash : "do_not_verify", status.getMime(), fileinfo); } @Override public long getContentLength() { return status.getLength(); } }; return this.write(file, status, command); }
B2WriteFeature extends AbstractHttpWriteFeature<BaseB2Response> implements Write<BaseB2Response> { @Override public HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException { final DelayedHttpEntityCallable<BaseB2Response> command = new DelayedHttpEntityCallable<BaseB2Response>() { @Override public BaseB2Response call(final AbstractHttpEntity entity) throws BackgroundException { try { final Checksum checksum = status.getChecksum(); if(status.isSegment()) { final B2GetUploadPartUrlResponse uploadUrl = session.getClient().getUploadPartUrl(status.getVersion().id); return session.getClient().uploadLargeFilePart(uploadUrl, status.getPart(), entity, checksum.hash); } else { if(null == urls.get()) { final B2GetUploadUrlResponse uploadUrl = session.getClient().getUploadUrl(fileid.getFileid(containerService.getContainer(file), new DisabledListProgressListener())); if(log.isDebugEnabled()) { log.debug(String.format("Obtained upload URL %s for file %s", uploadUrl, file)); } urls.set(uploadUrl); return this.upload(uploadUrl, entity, checksum); } else { final B2GetUploadUrlResponse uploadUrl = urls.get(); if(log.isDebugEnabled()) { log.debug(String.format("Use cached upload URL %s for file %s", uploadUrl, file)); } try { return this.upload(uploadUrl, entity, checksum); } catch(IOException | B2ApiException e) { log.warn(String.format("Remove cached upload URL after failure %s", e)); urls.remove(); return this.upload(uploadUrl, entity, checksum); } } } } catch(B2ApiException e) { throw new B2ExceptionMappingService().map("Upload {0} failed", e, file); } catch(IOException e) { throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file); } } protected BaseB2Response upload(final B2GetUploadUrlResponse uploadUrl, final AbstractHttpEntity entity, final Checksum checksum) throws B2ApiException, IOException, BackgroundException { final Map<String, String> fileinfo = new HashMap<>(status.getMetadata()); if(null != status.getTimestamp()) { fileinfo.put(X_BZ_INFO_SRC_LAST_MODIFIED_MILLIS, String.valueOf(status.getTimestamp())); } return session.getClient().uploadFile(uploadUrl, containerService.getKey(file), entity, checksum.algorithm == HashAlgorithm.sha1 ? checksum.hash : "do_not_verify", status.getMime(), fileinfo); } @Override public long getContentLength() { return status.getLength(); } }; return this.write(file, status, command); } }
B2WriteFeature extends AbstractHttpWriteFeature<BaseB2Response> implements Write<BaseB2Response> { @Override public HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException { final DelayedHttpEntityCallable<BaseB2Response> command = new DelayedHttpEntityCallable<BaseB2Response>() { @Override public BaseB2Response call(final AbstractHttpEntity entity) throws BackgroundException { try { final Checksum checksum = status.getChecksum(); if(status.isSegment()) { final B2GetUploadPartUrlResponse uploadUrl = session.getClient().getUploadPartUrl(status.getVersion().id); return session.getClient().uploadLargeFilePart(uploadUrl, status.getPart(), entity, checksum.hash); } else { if(null == urls.get()) { final B2GetUploadUrlResponse uploadUrl = session.getClient().getUploadUrl(fileid.getFileid(containerService.getContainer(file), new DisabledListProgressListener())); if(log.isDebugEnabled()) { log.debug(String.format("Obtained upload URL %s for file %s", uploadUrl, file)); } urls.set(uploadUrl); return this.upload(uploadUrl, entity, checksum); } else { final B2GetUploadUrlResponse uploadUrl = urls.get(); if(log.isDebugEnabled()) { log.debug(String.format("Use cached upload URL %s for file %s", uploadUrl, file)); } try { return this.upload(uploadUrl, entity, checksum); } catch(IOException | B2ApiException e) { log.warn(String.format("Remove cached upload URL after failure %s", e)); urls.remove(); return this.upload(uploadUrl, entity, checksum); } } } } catch(B2ApiException e) { throw new B2ExceptionMappingService().map("Upload {0} failed", e, file); } catch(IOException e) { throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file); } } protected BaseB2Response upload(final B2GetUploadUrlResponse uploadUrl, final AbstractHttpEntity entity, final Checksum checksum) throws B2ApiException, IOException, BackgroundException { final Map<String, String> fileinfo = new HashMap<>(status.getMetadata()); if(null != status.getTimestamp()) { fileinfo.put(X_BZ_INFO_SRC_LAST_MODIFIED_MILLIS, String.valueOf(status.getTimestamp())); } return session.getClient().uploadFile(uploadUrl, containerService.getKey(file), entity, checksum.algorithm == HashAlgorithm.sha1 ? checksum.hash : "do_not_verify", status.getMime(), fileinfo); } @Override public long getContentLength() { return status.getLength(); } }; return this.write(file, status, command); } B2WriteFeature(final B2Session session, final B2FileidProvider fileid);  B2WriteFeature(final B2Session session, final B2FileidProvider fileid, final Find finder, final AttributesFinder attributes); }
B2WriteFeature extends AbstractHttpWriteFeature<BaseB2Response> implements Write<BaseB2Response> { @Override public HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException { final DelayedHttpEntityCallable<BaseB2Response> command = new DelayedHttpEntityCallable<BaseB2Response>() { @Override public BaseB2Response call(final AbstractHttpEntity entity) throws BackgroundException { try { final Checksum checksum = status.getChecksum(); if(status.isSegment()) { final B2GetUploadPartUrlResponse uploadUrl = session.getClient().getUploadPartUrl(status.getVersion().id); return session.getClient().uploadLargeFilePart(uploadUrl, status.getPart(), entity, checksum.hash); } else { if(null == urls.get()) { final B2GetUploadUrlResponse uploadUrl = session.getClient().getUploadUrl(fileid.getFileid(containerService.getContainer(file), new DisabledListProgressListener())); if(log.isDebugEnabled()) { log.debug(String.format("Obtained upload URL %s for file %s", uploadUrl, file)); } urls.set(uploadUrl); return this.upload(uploadUrl, entity, checksum); } else { final B2GetUploadUrlResponse uploadUrl = urls.get(); if(log.isDebugEnabled()) { log.debug(String.format("Use cached upload URL %s for file %s", uploadUrl, file)); } try { return this.upload(uploadUrl, entity, checksum); } catch(IOException | B2ApiException e) { log.warn(String.format("Remove cached upload URL after failure %s", e)); urls.remove(); return this.upload(uploadUrl, entity, checksum); } } } } catch(B2ApiException e) { throw new B2ExceptionMappingService().map("Upload {0} failed", e, file); } catch(IOException e) { throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file); } } protected BaseB2Response upload(final B2GetUploadUrlResponse uploadUrl, final AbstractHttpEntity entity, final Checksum checksum) throws B2ApiException, IOException, BackgroundException { final Map<String, String> fileinfo = new HashMap<>(status.getMetadata()); if(null != status.getTimestamp()) { fileinfo.put(X_BZ_INFO_SRC_LAST_MODIFIED_MILLIS, String.valueOf(status.getTimestamp())); } return session.getClient().uploadFile(uploadUrl, containerService.getKey(file), entity, checksum.algorithm == HashAlgorithm.sha1 ? checksum.hash : "do_not_verify", status.getMime(), fileinfo); } @Override public long getContentLength() { return status.getLength(); } }; return this.write(file, status, command); } B2WriteFeature(final B2Session session, final B2FileidProvider fileid);  B2WriteFeature(final B2Session session, final B2FileidProvider fileid, final Find finder, final AttributesFinder attributes); @Override HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback); @Override boolean temporary(); @Override boolean random(); @Override ChecksumCompute checksum(final Path file, final TransferStatus status); @Override Append append(final Path file, final Long length, final Cache<Path> cache); }
B2WriteFeature extends AbstractHttpWriteFeature<BaseB2Response> implements Write<BaseB2Response> { @Override public HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback) throws BackgroundException { final DelayedHttpEntityCallable<BaseB2Response> command = new DelayedHttpEntityCallable<BaseB2Response>() { @Override public BaseB2Response call(final AbstractHttpEntity entity) throws BackgroundException { try { final Checksum checksum = status.getChecksum(); if(status.isSegment()) { final B2GetUploadPartUrlResponse uploadUrl = session.getClient().getUploadPartUrl(status.getVersion().id); return session.getClient().uploadLargeFilePart(uploadUrl, status.getPart(), entity, checksum.hash); } else { if(null == urls.get()) { final B2GetUploadUrlResponse uploadUrl = session.getClient().getUploadUrl(fileid.getFileid(containerService.getContainer(file), new DisabledListProgressListener())); if(log.isDebugEnabled()) { log.debug(String.format("Obtained upload URL %s for file %s", uploadUrl, file)); } urls.set(uploadUrl); return this.upload(uploadUrl, entity, checksum); } else { final B2GetUploadUrlResponse uploadUrl = urls.get(); if(log.isDebugEnabled()) { log.debug(String.format("Use cached upload URL %s for file %s", uploadUrl, file)); } try { return this.upload(uploadUrl, entity, checksum); } catch(IOException | B2ApiException e) { log.warn(String.format("Remove cached upload URL after failure %s", e)); urls.remove(); return this.upload(uploadUrl, entity, checksum); } } } } catch(B2ApiException e) { throw new B2ExceptionMappingService().map("Upload {0} failed", e, file); } catch(IOException e) { throw new DefaultIOExceptionMappingService().map("Upload {0} failed", e, file); } } protected BaseB2Response upload(final B2GetUploadUrlResponse uploadUrl, final AbstractHttpEntity entity, final Checksum checksum) throws B2ApiException, IOException, BackgroundException { final Map<String, String> fileinfo = new HashMap<>(status.getMetadata()); if(null != status.getTimestamp()) { fileinfo.put(X_BZ_INFO_SRC_LAST_MODIFIED_MILLIS, String.valueOf(status.getTimestamp())); } return session.getClient().uploadFile(uploadUrl, containerService.getKey(file), entity, checksum.algorithm == HashAlgorithm.sha1 ? checksum.hash : "do_not_verify", status.getMime(), fileinfo); } @Override public long getContentLength() { return status.getLength(); } }; return this.write(file, status, command); } B2WriteFeature(final B2Session session, final B2FileidProvider fileid);  B2WriteFeature(final B2Session session, final B2FileidProvider fileid, final Find finder, final AttributesFinder attributes); @Override HttpResponseOutputStream<BaseB2Response> write(final Path file, final TransferStatus status, final ConnectionCallback callback); @Override boolean temporary(); @Override boolean random(); @Override ChecksumCompute checksum(final Path file, final TransferStatus status); @Override Append append(final Path file, final Long length, final Cache<Path> cache);  }