public void run() { for (ResumableProcessor p : resumableProcessors) { p.save(resumableIndex); } } }
public ResumableAsyncHandler(long byteTransferred, AsyncHandler<Response> decoratedAsyncHandler) { this(byteTransferred, new PropertiesBasedResumableProcessor(), decoratedAsyncHandler, false); }
private ResumableAsyncHandler(long byteTransferred, ResumableProcessor resumableProcessor, AsyncHandler<Response> decoratedAsyncHandler, boolean accumulateBody) { this.byteTransferred = new AtomicLong(byteTransferred); if (resumableProcessor == null) { resumableProcessor = new NULLResumableHandler(); } this.resumableProcessor = resumableProcessor; resumableIndex = resumableProcessor.load(); resumeIndexThread.addResumableProcessor(resumableProcessor); this.decoratedAsyncHandler = decoratedAsyncHandler; this.accumulateBody = accumulateBody; }
@Test public void testRemove() { PropertiesBasedResumableProcessor propertiesProcessor = new PropertiesBasedResumableProcessor(); propertiesProcessor.put("http://localhost/test.url", 15L); propertiesProcessor.put("http://localhost/test2.url", 50L); propertiesProcessor.remove("http://localhost/test.url"); propertiesProcessor.save(null); propertiesProcessor = new PropertiesBasedResumableProcessor(); Map<String, Long> propertiesMap = propertiesProcessor.load(); assertEquals(propertiesMap.size(), 1); assertEquals(propertiesMap.get("http://localhost/test2.url"), Long.valueOf(50L)); } }
@Test public void testOnBodyPartReceivedWithResumableListenerThrowsException() throws Exception { ResumableAsyncHandler handler = new ResumableAsyncHandler(); ResumableListener resumableListener = mock(ResumableListener.class); doThrow(new IOException()).when(resumableListener).onBytesReceived(any()); handler.setResumableListener(resumableListener); HttpResponseBodyPart bodyPart = mock(HttpResponseBodyPart.class); State state = handler.onBodyPartReceived(bodyPart); assertEquals(state, AsyncHandler.State.ABORT, "State should be ABORT if the resumableListener threw an exception in onBodyPartReceived"); }
@Test public void testAdjustRange() { MapResumableProcessor proc = new MapResumableProcessor(); ResumableAsyncHandler handler = new ResumableAsyncHandler(proc); Request request = get("http://test/url").build(); Request newRequest = handler.adjustRequestRange(request); assertEquals(newRequest.getUri(), request.getUri()); String rangeHeader = newRequest.getHeaders().get(RANGE); assertNull(rangeHeader); proc.put("http://test/url", 5000); newRequest = handler.adjustRequestRange(request); assertEquals(newRequest.getUri(), request.getUri()); rangeHeader = newRequest.getHeaders().get(RANGE); assertEquals(rangeHeader, "bytes=5000-"); }
@Override public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { if (accumulateBody) { responseBuilder.accumulate(bodyPart); } State state = State.CONTINUE; try { resumableListener.onBytesReceived(bodyPart.getBodyByteBuffer()); } catch (IOException ex) { return AsyncHandler.State.ABORT; } if (decoratedAsyncHandler != null) { state = decoratedAsyncHandler.onBodyPartReceived(bodyPart); } byteTransferred.addAndGet(bodyPart.getBodyPartBytes().length); resumableProcessor.put(url, byteTransferred.get()); return state; }
@Test public void testOnStatusReceived500Status() throws Exception { MapResumableProcessor processor = new MapResumableProcessor(); ResumableAsyncHandler handler = new ResumableAsyncHandler(processor); HttpResponseStatus mockResponseStatus = mock(HttpResponseStatus.class); when(mockResponseStatus.getStatusCode()).thenReturn(500); when(mockResponseStatus.getUri()).thenReturn(mock(Uri.class)); State state = handler.onStatusReceived(mockResponseStatus); assertEquals(state, AsyncHandler.State.ABORT, "State should be ABORT for Internal Server Error status"); }
@Override public Response onCompleted() throws Exception { resumableProcessor.remove(url); resumableListener.onAllBytesReceived(); if (decoratedAsyncHandler != null) { decoratedAsyncHandler.onCompleted(); } // Not sure return responseBuilder.build(); }
@Test public void testOnHeadersReceived() throws Exception { ResumableAsyncHandler handler = new ResumableAsyncHandler(); HttpHeaders responseHeaders = new DefaultHttpHeaders(); State status = handler.onHeadersReceived(responseHeaders); assertEquals(status, AsyncHandler.State.CONTINUE, "State should be CONTINUE for a successful onHeadersReceived"); }
public <T> FilterContext<T> filter(FilterContext<T> ctx) { if (ctx.getIOException() != null && ctx.getAsyncHandler() instanceof ResumableAsyncHandler) { Request request = ResumableAsyncHandler.class.cast(ctx.getAsyncHandler()).adjustRequestRange(ctx.getRequest()); return new FilterContext.FilterContextBuilder<>(ctx).request(request).replayRequest(true).build(); } return ctx; } }
@Test public void testOnBytesReceivedBufferHasArray() throws IOException { RandomAccessFile file = mock(RandomAccessFile.class); ResumableRandomAccessFileListener listener = new ResumableRandomAccessFileListener(file); byte[] array = new byte[]{1, 2, 23, 33}; ByteBuffer buf = ByteBuffer.wrap(array); listener.onBytesReceived(buf); verify(file).write(array, 0, 4); }
@Test public void testOnBodyPartReceived() throws Exception { ResumableAsyncHandler handler = new ResumableAsyncHandler(); HttpResponseBodyPart bodyPart = mock(HttpResponseBodyPart.class); when(bodyPart.getBodyPartBytes()).thenReturn(new byte[0]); ByteBuffer buffer = ByteBuffer.allocate(0); when(bodyPart.getBodyByteBuffer()).thenReturn(buffer); State state = handler.onBodyPartReceived(bodyPart); assertEquals(state, AsyncHandler.State.CONTINUE, "State should be CONTINUE for a successful onBodyPartReceived"); }
@Test public void testSaveLoad() { PropertiesBasedResumableProcessor p = new PropertiesBasedResumableProcessor(); p.put("http://localhost/test.url", 15L); p.put("http://localhost/test2.url", 50L); p.save(null); p = new PropertiesBasedResumableProcessor(); Map<String, Long> m = p.load(); assertEquals(m.size(), 2); assertEquals(m.get("http://localhost/test.url"), Long.valueOf(15L)); assertEquals(m.get("http://localhost/test2.url"), Long.valueOf(50L)); }
@Test public void testOnStatusReceived206Status() throws Exception { MapResumableProcessor processor = new MapResumableProcessor(); ResumableAsyncHandler handler = new ResumableAsyncHandler(processor); HttpResponseStatus responseStatus206 = mock(HttpResponseStatus.class); when(responseStatus206.getStatusCode()).thenReturn(206); when(responseStatus206.getUri()).thenReturn(mock(Uri.class)); State state = handler.onStatusReceived(responseStatus206); assertEquals(state, AsyncHandler.State.CONTINUE, "Status should be CONTINUE for a 'Partial Content' response"); }
public ResumableAsyncHandler(AsyncHandler<Response> decoratedAsyncHandler) { this(0, new PropertiesBasedResumableProcessor(), decoratedAsyncHandler, false); }
@Test public void testOnHeadersReceivedContentLengthMinus() throws Exception { ResumableAsyncHandler handler = new ResumableAsyncHandler(); HttpHeaders responseHeaders = new DefaultHttpHeaders(); responseHeaders.add(CONTENT_LENGTH, -1); State status = handler.onHeadersReceived(responseHeaders); assertEquals(status, AsyncHandler.State.ABORT, "State should be ABORT for content length -1"); } }
@Test public void testOnBytesReceivedBufferHasNoArray() throws IOException { RandomAccessFile file = mock(RandomAccessFile.class); ResumableRandomAccessFileListener listener = new ResumableRandomAccessFileListener(file); byte[] byteArray = new byte[]{1, 2, 23, 33}; ByteBuffer buf = ByteBuffer.allocateDirect(4); buf.put(byteArray); buf.flip(); listener.onBytesReceived(buf); verify(file).write(byteArray); }
@Test public void testOnStatusReceivedOkStatus() throws Exception { MapResumableProcessor processor = new MapResumableProcessor(); ResumableAsyncHandler handler = new ResumableAsyncHandler(processor); HttpResponseStatus responseStatus200 = mock(HttpResponseStatus.class); when(responseStatus200.getStatusCode()).thenReturn(200); when(responseStatus200.getUri()).thenReturn(mock(Uri.class)); State state = handler.onStatusReceived(responseStatus200); assertEquals(state, AsyncHandler.State.CONTINUE, "Status should be CONTINUE for a OK response"); }
@Test public void testOnHeadersReceivedWithDecoratedAsyncHandler() throws Exception { HttpHeaders responseHeaders = new DefaultHttpHeaders(); @SuppressWarnings("unchecked") AsyncHandler<Response> decoratedAsyncHandler = mock(AsyncHandler.class); when(decoratedAsyncHandler.onHeadersReceived(responseHeaders)).thenReturn(State.CONTINUE); ResumableAsyncHandler handler = new ResumableAsyncHandler(decoratedAsyncHandler); State status = handler.onHeadersReceived(responseHeaders); assertEquals(status, State.CONTINUE, "State should be equal to the state returned from decoratedAsyncHandler"); }