From 156b6c565065a8cb200de2dbe922e4f49b7f8e03 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 1 Mar 2021 13:52:14 -0500 Subject: [PATCH 1/3] - renames large file upload to match specification --- spotBugsExcludeFilter.xml | 4 ++-- .../IProgressCallback.java | 2 +- .../IUploadSession.java | 2 +- .../LargeFileUploadRequest.java} | 20 ++++++++--------- .../LargeFileUploadResponseHandler.java} | 22 +++++++++---------- .../LargeFileUploadResult.java} | 12 +++++----- .../LargeFileUploadTask.java} | 16 +++++++------- 7 files changed, 39 insertions(+), 39 deletions(-) rename src/main/java/com/microsoft/graph/{concurrency => tasks}/IProgressCallback.java (97%) rename src/main/java/com/microsoft/graph/{concurrency => tasks}/IUploadSession.java (98%) rename src/main/java/com/microsoft/graph/{concurrency/ChunkedUploadRequest.java => tasks/LargeFileUploadRequest.java} (80%) rename src/main/java/com/microsoft/graph/{concurrency/ChunkedUploadResponseHandler.java => tasks/LargeFileUploadResponseHandler.java} (84%) rename src/main/java/com/microsoft/graph/{concurrency/ChunkedUploadResult.java => tasks/LargeFileUploadResult.java} (88%) rename src/main/java/com/microsoft/graph/{concurrency/ChunkedUploadProvider.java => tasks/LargeFileUploadTask.java} (94%) diff --git a/spotBugsExcludeFilter.xml b/spotBugsExcludeFilter.xml index 31e4a5f86..c6b2fff2e 100644 --- a/spotBugsExcludeFilter.xml +++ b/spotBugsExcludeFilter.xml @@ -9,11 +9,11 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu - + - + diff --git a/src/main/java/com/microsoft/graph/concurrency/IProgressCallback.java b/src/main/java/com/microsoft/graph/tasks/IProgressCallback.java similarity index 97% rename from src/main/java/com/microsoft/graph/concurrency/IProgressCallback.java rename to src/main/java/com/microsoft/graph/tasks/IProgressCallback.java index 66a295e5c..0a27f5d4f 100644 --- a/src/main/java/com/microsoft/graph/concurrency/IProgressCallback.java +++ b/src/main/java/com/microsoft/graph/tasks/IProgressCallback.java @@ -20,7 +20,7 @@ // THE SOFTWARE. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; /** * A callback that describes how to deal with success, failure, and progress diff --git a/src/main/java/com/microsoft/graph/concurrency/IUploadSession.java b/src/main/java/com/microsoft/graph/tasks/IUploadSession.java similarity index 98% rename from src/main/java/com/microsoft/graph/concurrency/IUploadSession.java rename to src/main/java/com/microsoft/graph/tasks/IUploadSession.java index 49e36e220..717bdde43 100644 --- a/src/main/java/com/microsoft/graph/concurrency/IUploadSession.java +++ b/src/main/java/com/microsoft/graph/tasks/IUploadSession.java @@ -20,7 +20,7 @@ // THE SOFTWARE. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; import java.util.List; diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java similarity index 80% rename from src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java rename to src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java index 7b9d6a10a..fac314089 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadRequest.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; import java.util.List; import java.util.Locale; @@ -21,7 +21,7 @@ * The chunk upload request. * @param The upload item type. */ -public class ChunkedUploadRequest { +public class LargeFileUploadRequest { /** * Content Range header name. @@ -41,7 +41,7 @@ public class ChunkedUploadRequest { /** * The base request. */ - private final BaseRequest> baseRequest; + private final BaseRequest> baseRequest; /** * Construct the ChunkedUploadRequest @@ -55,7 +55,7 @@ public class ChunkedUploadRequest { * @param totalLength The total length of the input stream. */ @SuppressWarnings("unchecked") - protected ChunkedUploadRequest(@Nonnull final String requestUrl, + protected LargeFileUploadRequest(@Nonnull final String requestUrl, @Nonnull final IBaseClient client, @Nullable final List options, @Nonnull final byte[] chunk, @@ -67,7 +67,7 @@ protected ChunkedUploadRequest(@Nonnull final String requestUrl, Objects.requireNonNull(chunk, "parameter chunk cannot be null"); this.data = new byte[chunkSize]; System.arraycopy(chunk, 0, this.data, 0, chunkSize); - this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new ChunkedUploadResult<>((UploadType)null)).getClass()) { + this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new LargeFileUploadResult<>((UploadType)null)).getClass()) { }; this.baseRequest.setHttpMethod(HttpMethod.PUT); this.baseRequest.addHeader(CONTENT_RANGE_HEADER_NAME, @@ -86,16 +86,16 @@ protected ChunkedUploadRequest(@Nonnull final String requestUrl, */ @SuppressWarnings("unchecked") @Nonnull - public ChunkedUploadResult upload( - @Nonnull final ChunkedUploadResponseHandler responseHandler) { + public LargeFileUploadResult upload( + @Nonnull final LargeFileUploadResponseHandler responseHandler) { Objects.requireNonNull(responseHandler, "parameter responseHandler cannot be null"); - ChunkedUploadResult result = null; + LargeFileUploadResult result = null; try { result = this.baseRequest .getClient() .getHttpProvider() - .send(baseRequest, (Class>)(Class) ChunkedUploadResult.class, this.data, responseHandler); + .send(baseRequest, (Class>)(Class) LargeFileUploadResult.class, this.data, responseHandler); } catch (final ClientException e) { throw new ClientException("Request failed with error, retry if necessary.", e); } @@ -103,7 +103,7 @@ public ChunkedUploadResult upload( if (result != null && result.chunkCompleted()) { return result; } else - return new ChunkedUploadResult( + return new LargeFileUploadResult( new ClientException("Upload session failed.", result == null ? null : result.getError())); } } diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java similarity index 84% rename from src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java rename to src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java index c571407a0..40ab93779 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java @@ -20,7 +20,7 @@ // THE SOFTWARE. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; import com.google.common.io.ByteStreams; @@ -51,8 +51,8 @@ * * @param the expected uploaded item */ -public class ChunkedUploadResponseHandler - implements IStatefulResponseHandler, UploadType> { +public class LargeFileUploadResponseHandler + implements IStatefulResponseHandler, UploadType> { /** * The expected deserialized upload type */ @@ -65,7 +65,7 @@ public class ChunkedUploadResponseHandler * @param uploadType the expected upload item type * @param uploadSessionType the type of the upload session */ - protected ChunkedUploadResponseHandler(@Nonnull final Class uploadType, @Nonnull final Class uploadSessionType) { + protected LargeFileUploadResponseHandler(@Nonnull final Class uploadType, @Nonnull final Class uploadSessionType) { this.deserializeTypeClass = Objects.requireNonNull(uploadType, "parameter uploadType cannot be null"); this.uploadSessionClass = Objects.requireNonNull(uploadSessionType, "parameter uploadSessionType cannot be null"); } @@ -92,7 +92,7 @@ public void configConnection(@Nonnull final Response response) { */ @Override @Nullable - public ChunkedUploadResult generateResult( + public LargeFileUploadResult generateResult( @Nonnull final IHttpRequest request, @Nonnull final Response response, @Nonnull final ISerializer serializer, @@ -104,7 +104,7 @@ public ChunkedUploadResult generateResult( if (response.code() >= HttpResponseCode.HTTP_CLIENT_ERROR) { logger.logDebug("Receiving error during upload, see detail on result error"); - return new ChunkedUploadResult<>( + return new LargeFileUploadResult<>( GraphServiceException.createFromResponse(request, null, serializer, response, logger)); } else if (response.code() >= HTTP_OK @@ -117,17 +117,17 @@ public ChunkedUploadResult generateResult( return parseJsonUploadResult(body, serializer, logger); } else if (location != null) { logger.logDebug("Upload session is completed (Outlook), uploaded item returned."); - return new ChunkedUploadResult<>(this.deserializeTypeClass.getDeclaredConstructor().newInstance()); + return new LargeFileUploadResult<>(this.deserializeTypeClass.getDeclaredConstructor().newInstance()); } else { logger.logDebug("Upload session returned an unexpected response"); } } } - return new ChunkedUploadResult<>(new ClientException("Received an unexpected response from the service, response code: " + response.code(), null)); + return new LargeFileUploadResult<>(new ClientException("Received an unexpected response from the service, response code: " + response.code(), null)); } @Nonnull - private ChunkedUploadResult parseJsonUploadResult(@Nonnull final ResponseBody responseBody, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws IOException { + private LargeFileUploadResult parseJsonUploadResult(@Nonnull final ResponseBody responseBody, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws IOException { try (final InputStream in = responseBody.byteStream()) { final byte[] responseBytes = ByteStreams.toByteArray(in); final IUploadSession session = serializer.deserializeObject(new ByteArrayInputStream(responseBytes), uploadSessionClass); @@ -135,10 +135,10 @@ private ChunkedUploadResult parseJsonUploadResult(@Nonnull final Res if (session == null || session.getNextExpectedRanges() == null) { logger.logDebug("Upload session is completed (ODSP), uploaded item returned."); final UploadType uploadedItem = serializer.deserializeObject(new ByteArrayInputStream(responseBytes), this.deserializeTypeClass); - return new ChunkedUploadResult<>(uploadedItem); + return new LargeFileUploadResult<>(uploadedItem); } else { logger.logDebug("Chunk bytes has been accepted by the server."); - return new ChunkedUploadResult<>(session); + return new LargeFileUploadResult<>(session); } } } diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java similarity index 88% rename from src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java rename to src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java index 7894bb55c..1d93a06fe 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResult.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; import com.microsoft.graph.core.ClientException; import com.microsoft.graph.http.GraphServiceException; @@ -16,7 +16,7 @@ /** * Wrapper class for different upload response from server. */ -public class ChunkedUploadResult { +public class LargeFileUploadResult { /** * The uploaded item response. */ @@ -37,7 +37,7 @@ public class ChunkedUploadResult { * * @param uploaded The created item. */ - protected ChunkedUploadResult(@Nullable final UploadType uploaded) { + protected LargeFileUploadResult(@Nullable final UploadType uploaded) { this.uploadedItem = uploaded; this.session = null; this.error = null; @@ -48,7 +48,7 @@ protected ChunkedUploadResult(@Nullable final UploadType uploaded) { * * @param session The next session. */ - protected ChunkedUploadResult(@Nullable final IUploadSession session) { + protected LargeFileUploadResult(@Nullable final IUploadSession session) { this.session = session; this.uploadedItem = null; this.error = null; @@ -59,7 +59,7 @@ protected ChunkedUploadResult(@Nullable final IUploadSession session) { * * @param error The error occurred during uploading. */ - protected ChunkedUploadResult(@Nullable final ClientException error) { + protected LargeFileUploadResult(@Nullable final ClientException error) { this.error = error; this.uploadedItem = null; this.session = null; @@ -70,7 +70,7 @@ protected ChunkedUploadResult(@Nullable final ClientException error) { * * @param exception The exception received from server. */ - protected ChunkedUploadResult(@Nonnull final GraphServiceException exception) { + protected LargeFileUploadResult(@Nonnull final GraphServiceException exception) { this(new ClientException(Objects .requireNonNull(exception, "parameter exception cannot be null") .getMessage(/* verbose */ true), diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java similarity index 94% rename from src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java rename to src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java index ce0c61989..7db50f8a2 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadProvider.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java @@ -20,7 +20,7 @@ // THE SOFTWARE. // ------------------------------------------------------------------------------ -package com.microsoft.graph.concurrency; +package com.microsoft.graph.tasks; import com.microsoft.graph.core.ClientException; import com.microsoft.graph.core.IBaseClient; @@ -42,7 +42,7 @@ * * @param the upload item type */ -public class ChunkedUploadProvider { +public class LargeFileUploadTask { /** * The default chunk size for upload. Currently set to 5 MiB. @@ -83,7 +83,7 @@ public class ChunkedUploadProvider { /** * The upload response handler */ - private final ChunkedUploadResponseHandler responseHandler; + private final LargeFileUploadResponseHandler responseHandler; /** * The counter for how many bytes have been read from input stream @@ -99,7 +99,7 @@ public class ChunkedUploadProvider { * @param streamSize the stream size * @param uploadTypeClass the upload type class */ - public ChunkedUploadProvider(@Nonnull final IUploadSession uploadSession, + public LargeFileUploadTask(@Nonnull final IUploadSession uploadSession, @Nonnull final IBaseClient client, @Nonnull final InputStream inputStream, final long streamSize, @@ -115,7 +115,7 @@ public ChunkedUploadProvider(@Nonnull final IUploadSession uploadSession, this.inputStream = Objects.requireNonNull(inputStream, "Input stream is null."); this.streamSize = streamSize; this.uploadUrl = uploadSession.getUploadUrl(); - this.responseHandler = new ChunkedUploadResponseHandler(uploadTypeClass, uploadSession.getClass()); + this.responseHandler = new LargeFileUploadResponseHandler(uploadTypeClass, uploadSession.getClass()); } /** @@ -159,10 +159,10 @@ public java.util.concurrent.CompletableFuture uploadAsync(@Nullable buffRead += read; } - final ChunkedUploadRequest request = - new ChunkedUploadRequest<>(this.uploadUrl, this.client, options, buffer, buffRead, + final LargeFileUploadRequest request = + new LargeFileUploadRequest<>(this.uploadUrl, this.client, options, buffer, buffRead, this.readSoFar, this.streamSize); - final ChunkedUploadResult result = request.upload(this.responseHandler); + final LargeFileUploadResult result = request.upload(this.responseHandler); // TODO: upload should return a future, use sendfuture instead and the futures should be chained with completableFuture.then apply if (result.uploadCompleted()) { From ff4c5401a63137fbadbec1ffd8f3b1d4bb4273bd Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 1 Mar 2021 15:11:44 -0500 Subject: [PATCH 2/3] - remove references to native http type in interfaces - removes useless method in interface - adds result wrapper for consumers for large file uploads --- .../graph/http/CoreHttpProvider.java | 5 - .../graph/http/IStatefulResponseHandler.java | 14 +- .../graph/tasks/LargeFileUploadRequest.java | 14 +- .../graph/tasks/LargeFileUploadResponse.java | 163 ++++++++++++++++++ .../tasks/LargeFileUploadResponseHandler.java | 57 +++--- .../graph/tasks/LargeFileUploadResult.java | 130 +------------- .../graph/tasks/LargeFileUploadTask.java | 43 +++-- 7 files changed, 227 insertions(+), 199 deletions(-) create mode 100644 src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponse.java diff --git a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java index 3ee61dea2..59d6b04c4 100644 --- a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java +++ b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java @@ -404,11 +404,6 @@ private Result processResponse(final Response re // Call being executed - - if (handler != null) { - handler.configConnection(response); - } - logger.logDebug(String.format(Locale.ROOT, "Response code %d, %s", response.code(), response.message())); diff --git a/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java b/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java index b4343def5..893691a86 100644 --- a/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java +++ b/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java @@ -29,8 +29,6 @@ import javax.annotation.Nullable; import javax.annotation.Nonnull; -import okhttp3.Response; - /** * The handler interface for requests having stateful response from server. * The handler will custom the HTTP connection if needed and generate request @@ -40,13 +38,6 @@ * @param the deserialize type for serializer */ public interface IStatefulResponseHandler { - /** - * Configure the response - * - * @param response the HTTP response - */ - void configConnection(@Nonnull final Response response); - /** * Generate result after receiving response * @@ -54,12 +45,13 @@ public interface IStatefulResponseHandler { * @param response the HTTP connection * @param serializer the serializer for parsing response * @param logger the logger + * @param the native http client response type * @return the result generated by this handler * @throws Exception an exception occurs if the request was unable to complete for any reason */ @Nullable - ResultType generateResult(@Nonnull final IHttpRequest request, - @Nonnull final Response response, + ResultType generateResult(@Nonnull final IHttpRequest request, + @Nonnull final ResponseType response, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws Exception; } diff --git a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java index fac314089..286c10d1a 100644 --- a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadRequest.java @@ -21,7 +21,7 @@ * The chunk upload request. * @param The upload item type. */ -public class LargeFileUploadRequest { +class LargeFileUploadRequest { /** * Content Range header name. @@ -41,7 +41,7 @@ public class LargeFileUploadRequest { /** * The base request. */ - private final BaseRequest> baseRequest; + private final BaseRequest> baseRequest; /** * Construct the ChunkedUploadRequest @@ -67,7 +67,7 @@ protected LargeFileUploadRequest(@Nonnull final String requestUrl, Objects.requireNonNull(chunk, "parameter chunk cannot be null"); this.data = new byte[chunkSize]; System.arraycopy(chunk, 0, this.data, 0, chunkSize); - this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new LargeFileUploadResult<>((UploadType)null)).getClass()) { + this.baseRequest = new BaseRequest>(requestUrl, client, options, (Class>)(new LargeFileUploadResponse<>((UploadType)null)).getClass()) { }; this.baseRequest.setHttpMethod(HttpMethod.PUT); this.baseRequest.addHeader(CONTENT_RANGE_HEADER_NAME, @@ -86,16 +86,16 @@ protected LargeFileUploadRequest(@Nonnull final String requestUrl, */ @SuppressWarnings("unchecked") @Nonnull - public LargeFileUploadResult upload( + public LargeFileUploadResponse upload( @Nonnull final LargeFileUploadResponseHandler responseHandler) { Objects.requireNonNull(responseHandler, "parameter responseHandler cannot be null"); - LargeFileUploadResult result = null; + LargeFileUploadResponse result = null; try { result = this.baseRequest .getClient() .getHttpProvider() - .send(baseRequest, (Class>)(Class) LargeFileUploadResult.class, this.data, responseHandler); + .send(baseRequest, (Class>)(Class) LargeFileUploadResponse.class, this.data, responseHandler); } catch (final ClientException e) { throw new ClientException("Request failed with error, retry if necessary.", e); } @@ -103,7 +103,7 @@ public LargeFileUploadResult upload( if (result != null && result.chunkCompleted()) { return result; } else - return new LargeFileUploadResult( + return new LargeFileUploadResponse( new ClientException("Upload session failed.", result == null ? null : result.getError())); } } diff --git a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponse.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponse.java new file mode 100644 index 000000000..bbf2a53a4 --- /dev/null +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponse.java @@ -0,0 +1,163 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +package com.microsoft.graph.tasks; + +import com.microsoft.graph.core.ClientException; +import com.microsoft.graph.http.GraphServiceException; + +import javax.annotation.Nullable; + +import java.util.Objects; + +import javax.annotation.Nonnull; + +/** + * Wrapper class for different upload response from server. + */ +class LargeFileUploadResponse { + /** + * The location header from the response if provided + */ + private final String location; + /** + * The uploaded item response. + */ + private final UploadType uploadedItem; + + /** + * The next session response. + */ + private final IUploadSession session; + + /** + * The error happened during upload. + */ + private final ClientException error; + + /** + * Constructs response with the location header. + * + * @param location The location returned by the response + */ + protected LargeFileUploadResponse(@Nullable final String location) { + this.location = location; + this.error = null; + this.session = null; + this.uploadedItem = null; + } + + /** + * Construct response with item created. + * + * @param uploaded The created item. + */ + protected LargeFileUploadResponse(@Nullable final UploadType uploaded) { + this.uploadedItem = uploaded; + this.session = null; + this.error = null; + this.location = null; + } + + /** + * Construct response with next session. + * + * @param session The next session. + */ + protected LargeFileUploadResponse(@Nullable final IUploadSession session) { + this.session = session; + this.uploadedItem = null; + this.error = null; + this.location = null; + } + + /** + * Construct response with error. + * + * @param error The error occurred during uploading. + */ + protected LargeFileUploadResponse(@Nullable final ClientException error) { + this.error = error; + this.uploadedItem = null; + this.session = null; + this.location = null; + } + + /** + * Construct response with server exception. + * + * @param exception The exception received from server. + */ + protected LargeFileUploadResponse(@Nonnull final GraphServiceException exception) { + this(new ClientException(Objects + .requireNonNull(exception, "parameter exception cannot be null") + .getMessage(/* verbose */ true), + exception)); + } + + /** + * Checks the large upload range is completed. + * + * @return true if current large upload range is completed. + */ + public boolean chunkCompleted() { + return this.uploadedItem != null || this.session != null; + } + + /** + * Checks the whole upload is completed. + * + * @return true if the response is an item. + */ + public boolean uploadCompleted() { + return this.uploadedItem != null || this.location != null; + } + + /** + * Checks if an error happened. + * + * @return true if current request has error. + */ + public boolean hasError() { + return this.error != null; + } + + /** + * Get the uploaded item. + * + * @return The item. + */ + @Nullable + public UploadType getItem() { + return this.uploadedItem; + } + + /** + * Get the next session. + * + * @return The next session for uploading. + */ + @Nullable + public IUploadSession getSession() { + return this.session; + } + + /** + * Get the error. + * + * @return The error. + */ + @Nullable + public ClientException getError() { + return this.error; + } + /** + * Get the location. + * @return The location. + */ + @Nullable + public String getLocation () { + return this.location; + } +} diff --git a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java index 40ab93779..9d28bbdb4 100644 --- a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResponseHandler.java @@ -51,8 +51,8 @@ * * @param the expected uploaded item */ -public class LargeFileUploadResponseHandler - implements IStatefulResponseHandler, UploadType> { +class LargeFileUploadResponseHandler + implements IStatefulResponseHandler, UploadType> { /** * The expected deserialized upload type */ @@ -70,64 +70,49 @@ protected LargeFileUploadResponseHandler(@Nonnull final Class upload this.uploadSessionClass = Objects.requireNonNull(uploadSessionType, "parameter uploadSessionType cannot be null"); } - /** - * Do nothing before getting the response - * - * @param response The response - */ - @Override - public void configConnection(@Nonnull final Response response) { - return; - } - - /** - * Generate the chunked upload response result - * - * @param request the HTTP request - * @param response the HTTP response - * @param serializer the serializer - * @param logger the system logger - * @return the chunked upload result, which could be either an uploaded item or error - * @throws Exception an exception occurs if the request was unable to complete for any reason - */ @Override @Nullable - public LargeFileUploadResult generateResult( + public LargeFileUploadResponse generateResult( @Nonnull final IHttpRequest request, - @Nonnull final Response response, + @Nonnull final ResponseType response, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws Exception { Objects.requireNonNull(request, "parameter request cannot be null"); Objects.requireNonNull(response, "parameter response cannot be null"); Objects.requireNonNull(serializer, "parameter serializer cannot be null"); Objects.requireNonNull(logger, "parameter logger cannot be null"); - if (response.code() >= HttpResponseCode.HTTP_CLIENT_ERROR) { + if(!(response instanceof Response)) { + throw new ClientException("unsupported response type", null); + } + final Response nativeResponse = (Response)response; + + if (nativeResponse.code() >= HttpResponseCode.HTTP_CLIENT_ERROR) { logger.logDebug("Receiving error during upload, see detail on result error"); - return new LargeFileUploadResult<>( + return new LargeFileUploadResponse<>( GraphServiceException.createFromResponse(request, null, serializer, - response, logger)); - } else if (response.code() >= HTTP_OK - && response.code() < HttpResponseCode.HTTP_MULTIPLE_CHOICES) { - try(final ResponseBody body = response.body()) { - final String location = response.headers().get("Location"); + nativeResponse, logger)); + } else if (nativeResponse.code() >= HTTP_OK + && nativeResponse.code() < HttpResponseCode.HTTP_MULTIPLE_CHOICES) { + try(final ResponseBody body = nativeResponse.body()) { + final String location = nativeResponse.headers().get("Location"); final MediaType contentType = body.contentType(); final String subType = contentType == null ? null : contentType.subtype(); if (subType != null && subType.contains("json")) { return parseJsonUploadResult(body, serializer, logger); } else if (location != null) { logger.logDebug("Upload session is completed (Outlook), uploaded item returned."); - return new LargeFileUploadResult<>(this.deserializeTypeClass.getDeclaredConstructor().newInstance()); + return new LargeFileUploadResponse<>(location); } else { logger.logDebug("Upload session returned an unexpected response"); } } } - return new LargeFileUploadResult<>(new ClientException("Received an unexpected response from the service, response code: " + response.code(), null)); + return new LargeFileUploadResponse<>(new ClientException("Received an unexpected response from the service, response code: " + nativeResponse.code(), null)); } @Nonnull - private LargeFileUploadResult parseJsonUploadResult(@Nonnull final ResponseBody responseBody, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws IOException { + private LargeFileUploadResponse parseJsonUploadResult(@Nonnull final ResponseBody responseBody, @Nonnull final ISerializer serializer, @Nonnull final ILogger logger) throws IOException { try (final InputStream in = responseBody.byteStream()) { final byte[] responseBytes = ByteStreams.toByteArray(in); final IUploadSession session = serializer.deserializeObject(new ByteArrayInputStream(responseBytes), uploadSessionClass); @@ -135,10 +120,10 @@ private LargeFileUploadResult parseJsonUploadResult(@Nonnull final R if (session == null || session.getNextExpectedRanges() == null) { logger.logDebug("Upload session is completed (ODSP), uploaded item returned."); final UploadType uploadedItem = serializer.deserializeObject(new ByteArrayInputStream(responseBytes), this.deserializeTypeClass); - return new LargeFileUploadResult<>(uploadedItem); + return new LargeFileUploadResponse<>(uploadedItem); } else { logger.logDebug("Chunk bytes has been accepted by the server."); - return new LargeFileUploadResult<>(session); + return new LargeFileUploadResponse<>(session); } } } diff --git a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java index 1d93a06fe..b1459adbc 100644 --- a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadResult.java @@ -1,136 +1,22 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. -// ------------------------------------------------------------------------------ - package com.microsoft.graph.tasks; -import com.microsoft.graph.core.ClientException; -import com.microsoft.graph.http.GraphServiceException; - import javax.annotation.Nullable; -import java.util.Objects; - -import javax.annotation.Nonnull; - /** - * Wrapper class for different upload response from server. + * Respresents the result of a large file upload task. + * + * @param type of the deserialized response. */ -public class LargeFileUploadResult { - /** - * The uploaded item response. - */ - private final UploadType uploadedItem; - - /** - * The next session response. - */ - private final IUploadSession session; - - /** - * The error happened during upload. - */ - private final ClientException error; - - /** - * Construct result with item created. - * - * @param uploaded The created item. - */ - protected LargeFileUploadResult(@Nullable final UploadType uploaded) { - this.uploadedItem = uploaded; - this.session = null; - this.error = null; - } - - /** - * Construct result with next session. - * - * @param session The next session. - */ - protected LargeFileUploadResult(@Nullable final IUploadSession session) { - this.session = session; - this.uploadedItem = null; - this.error = null; - } - - /** - * Construct result with error. - * - * @param error The error occurred during uploading. - */ - protected LargeFileUploadResult(@Nullable final ClientException error) { - this.error = error; - this.uploadedItem = null; - this.session = null; - } - - /** - * Construct result with server exception. - * - * @param exception The exception received from server. - */ - protected LargeFileUploadResult(@Nonnull final GraphServiceException exception) { - this(new ClientException(Objects - .requireNonNull(exception, "parameter exception cannot be null") - .getMessage(/* verbose */ true), - exception)); - } - - /** - * Checks the chunk upload is completed. - * - * @return true if current chunk upload is completed. - */ - public boolean chunkCompleted() { - return this.uploadedItem != null || this.session != null; - } - - /** - * Checks the whole upload is completed. - * - * @return true if the response is an item. - */ - public boolean uploadCompleted() { - return this.uploadedItem != null; - } - - /** - * Checks if an error happened. - * - * @return true if current request has error. - */ - public boolean hasError() { - return this.error != null; - } - - /** - * Get the uploaded item. - * - * @return The item. - */ - @Nullable - public UploadType getItem() { - return this.uploadedItem; - } - +public class LargeFileUploadResult { /** - * Get the next session. - * - * @return The next session for uploading. + * Location response header value if provided. */ @Nullable - public IUploadSession getSession() { - return this.session; - } + public String location; /** - * Get the error. - * - * @return The error. + * Deserialized response body if the response has content. */ @Nullable - public ClientException getError() { - return this.error; - } + public ResultType responseBody; } diff --git a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java index 7db50f8a2..0316d93cd 100644 --- a/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java +++ b/src/main/java/com/microsoft/graph/tasks/LargeFileUploadTask.java @@ -128,7 +128,7 @@ public LargeFileUploadTask(@Nonnull final IUploadSession uploadSession, * @throws IOException the IO exception that occurred during upload */ @Nonnull - public java.util.concurrent.CompletableFuture uploadAsync(@Nullable final int chunkSize, @Nullable final List