From 3c5266dd23f1f728b125b8ef16e1f4c757721044 Mon Sep 17 00:00:00 2001 From: Fernando F Costa <44307697+ffcdf@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:25:24 -0300 Subject: [PATCH 1/4] Update LargeFileUploadTask.java Suggested modification to the chunkInputStream method: From the second pass through this method, the code in the line "int lengthAssert = stream.read(buffer, begin, length);" throws the exception java.lang.IndexOutOfBoundsException when trying to assign the read bytes to a non-existent position in the buffer. The suggested change implies changing InputStream to FileInputStream throughout the LargeFileUploadTask class. --- .../graph/core/tasks/LargeFileUploadTask.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java index 9f02dfe27..8af1f0bd4 100644 --- a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java +++ b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java @@ -24,13 +24,15 @@ import jakarta.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; +import java.io.FileInputStream; import java.lang.reflect.InvocationTargetException; import java.time.OffsetDateTime; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; /** * Task for uploading large files including pausing and resuming. @@ -41,7 +43,7 @@ public class LargeFileUploadTask { private static final long DEFAULT_MAX_SLICE_SIZE = (long) 5*1024*1024; private IUploadSession uploadSession; private final RequestAdapter requestAdapter; - private final InputStream uploadStream; + private final FileInputStream uploadStream; private final long maxSliceSize; private ArrayList> rangesRemaining; private final long totalUploadLength; @@ -61,7 +63,7 @@ public class LargeFileUploadTask { */ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, @Nonnull Parsable uploadSession, - @Nonnull InputStream uploadStream, + @Nonnull FileInputStream uploadStream, long streamSize, @Nonnull ParsableFactory factory) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException { this(requestAdapter, uploadSession,uploadStream, streamSize,DEFAULT_MAX_SLICE_SIZE, factory); @@ -81,7 +83,7 @@ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, */ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, @Nonnull Parsable uploadSession, - @Nonnull InputStream uploadStream, + @Nonnull FileInputStream uploadStream, long streamSize, long maxSliceSize, @Nonnull ParsableFactory factory) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException { @@ -275,9 +277,12 @@ private long nextSliceSize(long rangeBegin, long rangeEnd) { long size = rangeEnd - rangeBegin + 1; return Math.min(size, this.maxSliceSize); } - private byte[] chunkInputStream(InputStream stream, int begin, int length) throws IOException { - byte[] buffer = new byte[length]; - int lengthAssert = stream.read(buffer, begin, length); + private byte[] chunkInputStream(FileInputStream stream, int begin, int length) throws IOException { + ByteBuffer byteBuffer = ByteBuffer.allocate(length); + int lengthAssert = stream.getChannel().read(byteBuffer); + byteBuffer.flip(); + byte[] buffer = byteBuffer.array(); + byteBuffer.clear(); assert lengthAssert == length; return buffer; } From b2c1e32458fae79a2d09a71f476948acc2031d02 Mon Sep 17 00:00:00 2001 From: Fernando F Costa <44307697+ffcdf@users.noreply.github.com> Date: Mon, 4 Mar 2024 13:54:59 -0300 Subject: [PATCH 2/4] Update LargeFileUploadTask.java --- .../graph/core/tasks/LargeFileUploadTask.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java index 8af1f0bd4..826c6959c 100644 --- a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java +++ b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java @@ -1,5 +1,23 @@ package com.microsoft.graph.core.tasks; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.time.OffsetDateTime; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import com.microsoft.graph.core.ErrorConstants; import com.microsoft.graph.core.exceptions.ClientException; import com.microsoft.graph.core.models.IProgressCallback; @@ -18,21 +36,8 @@ import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.ParsableFactory; import com.microsoft.kiota.serialization.ParseNode; -import okhttp3.OkHttpClient; -import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.FileInputStream; -import java.lang.reflect.InvocationTargetException; -import java.time.OffsetDateTime; -import java.util.*; -import java.util.concurrent.CancellationException; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; +import okhttp3.OkHttpClient; /** * Task for uploading large files including pausing and resuming. @@ -43,7 +48,7 @@ public class LargeFileUploadTask { private static final long DEFAULT_MAX_SLICE_SIZE = (long) 5*1024*1024; private IUploadSession uploadSession; private final RequestAdapter requestAdapter; - private final FileInputStream uploadStream; + private final InputStream uploadStream; private final long maxSliceSize; private ArrayList> rangesRemaining; private final long totalUploadLength; @@ -63,7 +68,7 @@ public class LargeFileUploadTask { */ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, @Nonnull Parsable uploadSession, - @Nonnull FileInputStream uploadStream, + @Nonnull InputStream uploadStream, long streamSize, @Nonnull ParsableFactory factory) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException { this(requestAdapter, uploadSession,uploadStream, streamSize,DEFAULT_MAX_SLICE_SIZE, factory); @@ -83,7 +88,7 @@ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, */ public LargeFileUploadTask(@Nullable final RequestAdapter requestAdapter, @Nonnull Parsable uploadSession, - @Nonnull FileInputStream uploadStream, + @Nonnull InputStream uploadStream, long streamSize, long maxSliceSize, @Nonnull ParsableFactory factory) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException { @@ -139,7 +144,7 @@ public UploadResult upload(int maxTries, @Nullable IProgressCallback progress return result; } } - updateSessionStatus(); + //updateSessionStatus(); uploadTries += 1; if (uploadTries < maxTries) { TimeUnit.SECONDS.sleep((long) 2 * uploadTries * uploadTries); @@ -203,7 +208,7 @@ public IUploadSession updateSessionStatus() { return session; } private UploadResult uploadSlice(UploadSliceRequestBuilder uploadSliceRequestBuilder, ArrayList exceptionsList) throws IOException { - byte[] buffer = chunkInputStream(uploadStream,(int) uploadSliceRequestBuilder.getRangeBegin(), (int)uploadSliceRequestBuilder.getRangeLength()); + byte[] buffer = chunkInputStream(uploadStream, (int)uploadSliceRequestBuilder.getRangeLength()); ByteArrayInputStream chunkStream = new ByteArrayInputStream(buffer); try { return uploadSliceRequestBuilder.put(chunkStream); @@ -277,12 +282,9 @@ private long nextSliceSize(long rangeBegin, long rangeEnd) { long size = rangeEnd - rangeBegin + 1; return Math.min(size, this.maxSliceSize); } - private byte[] chunkInputStream(FileInputStream stream, int begin, int length) throws IOException { - ByteBuffer byteBuffer = ByteBuffer.allocate(length); - int lengthAssert = stream.getChannel().read(byteBuffer); - byteBuffer.flip(); - byte[] buffer = byteBuffer.array(); - byteBuffer.clear(); + private byte[] chunkInputStream(InputStream stream, int length) throws IOException { + byte[] buffer = new byte[length]; + int lengthAssert = stream.read(buffer); assert lengthAssert == length; return buffer; } From 8ab1ecab3000db7766d2a761185a2fec728f857a Mon Sep 17 00:00:00 2001 From: Fernando F Costa <44307697+ffcdf@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:15:56 -0300 Subject: [PATCH 3/4] Update LargeFileUploadTask.java According to the documentation: public int read(byte[] b, int off, int len) throws IOException The first byte read is stored into element b[off], the next one into b[off+1], and so on. However, from the second pass through the chunkInputStream method, off is greater than any position of b and therefore, b[off] does not exist. --- .../graph/core/tasks/LargeFileUploadTask.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java index 826c6959c..566506d07 100644 --- a/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java +++ b/src/main/java/com/microsoft/graph/core/tasks/LargeFileUploadTask.java @@ -1,23 +1,5 @@ package com.microsoft.graph.core.tasks; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.time.OffsetDateTime; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CancellationException; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.microsoft.graph.core.ErrorConstants; import com.microsoft.graph.core.exceptions.ClientException; import com.microsoft.graph.core.models.IProgressCallback; @@ -36,9 +18,20 @@ import com.microsoft.kiota.serialization.Parsable; import com.microsoft.kiota.serialization.ParsableFactory; import com.microsoft.kiota.serialization.ParseNode; - import okhttp3.OkHttpClient; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.time.OffsetDateTime; +import java.util.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + /** * Task for uploading large files including pausing and resuming. * @param They type of Item that we will be uploading @@ -144,7 +137,7 @@ public UploadResult upload(int maxTries, @Nullable IProgressCallback progress return result; } } - //updateSessionStatus(); + updateSessionStatus(); uploadTries += 1; if (uploadTries < maxTries) { TimeUnit.SECONDS.sleep((long) 2 * uploadTries * uploadTries); From c24b1b37b0a730bd8a888ab1d8330e1446a7502b Mon Sep 17 00:00:00 2001 From: Fernando F Costa <44307697+ffcdf@users.noreply.github.com> Date: Mon, 11 Mar 2024 07:43:53 -0300 Subject: [PATCH 4/4] Update CHANGELOG.md Changed chunkInputStream method in LargeFileUploadTask to resolve IndexOutOfBoundsException when uploading large files --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 900a92d50..7ecbe1bed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [3.1.7] ### Added ### Changed +- Changed chunkInputStream method in LargeFileUploadTask to resolve IndexOutOfBoundsException when uploading large files ## [3.1.6] - 2024-02-29