diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml
index 7bb8af52b..5200b4e04 100644
--- a/.github/workflows/gradle-build.yml
+++ b/.github/workflows/gradle-build.yml
@@ -16,10 +16,6 @@ jobs:
java-version: 21
distribution: 'temurin'
cache: gradle
- - name: Detect secrets
- run: |
- pip install detect-secrets
- git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 39d5a95e9..d3d6d3e4e 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.6.3"
+ ".": "3.6.4"
}
diff --git a/.secrets.baseline b/.secrets.baseline
deleted file mode 100644
index 6bac09a59..000000000
--- a/.secrets.baseline
+++ /dev/null
@@ -1,113 +0,0 @@
-{
- "version": "1.5.0",
- "plugins_used": [
- {
- "name": "ArtifactoryDetector"
- },
- {
- "name": "AWSKeyDetector"
- },
- {
- "name": "AzureStorageKeyDetector"
- },
- {
- "name": "Base64HighEntropyString",
- "limit": 4.5
- },
- {
- "name": "BasicAuthDetector"
- },
- {
- "name": "CloudantDetector"
- },
- {
- "name": "HexHighEntropyString",
- "limit": 3.0
- },
- {
- "name": "IbmCloudIamDetector"
- },
- {
- "name": "IbmCosHmacDetector"
- },
- {
- "name": "JwtTokenDetector"
- },
- {
- "name": "KeywordDetector",
- "keyword_exclude": ""
- },
- {
- "name": "MailchimpDetector"
- },
- {
- "name": "NpmDetector"
- },
- {
- "name": "PrivateKeyDetector"
- },
- {
- "name": "SlackDetector"
- },
- {
- "name": "SoftlayerDetector"
- },
- {
- "name": "SquareOAuthDetector"
- },
- {
- "name": "StripeDetector"
- },
- {
- "name": "TwilioKeyDetector"
- }
- ],
- "filters_used": [
- {
- "path": "detect_secrets.filters.allowlist.is_line_allowlisted"
- },
- {
- "path": "detect_secrets.filters.common.is_baseline_file",
- "filename": ".secrets.baseline"
- },
- {
- "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
- "min_level": 2
- },
- {
- "path": "detect_secrets.filters.heuristic.is_indirect_reference"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_likely_id_string"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_lock_file"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_potential_uuid"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_sequential_string"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_swagger_file"
- },
- {
- "path": "detect_secrets.filters.heuristic.is_templated_secret"
- },
- {
- "path": "detect_secrets.filters.regex.should_exclude_file",
- "pattern": [
- "release-please-config.json"
- ]
- }
- ],
- "results": {},
- "generated_at": "2024-08-12T15:21:45Z"
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc9f38e22..7dda7202e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ 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).
+## [3.6.4](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.6.3...v3.6.4) (2025-07-04)
+
+
+### Bug Fixes
+
+* missing bytes when processing chunks of a file during upload ([e0dbff6](https://github.com/microsoftgraph/msgraph-sdk-java-core/commit/e0dbff6fe4b15b0cc661cf79d38152e2cb34d117))
+
## [3.6.3](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.6.2...v3.6.3) (2025-06-20)
diff --git a/README.md b/README.md
index 77548b02a..0d8984623 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ repositories {
dependencies {
// Include the sdk as a dependency
// x-release-please-start-version
- implementation 'com.microsoft.graph:microsoft-graph-core:3.6.3'
+ implementation 'com.microsoft.graph:microsoft-graph-core:3.6.4'
// x-release-please-end
// This dependency is only needed if you are using the TokenCredentialAuthProvider
implementation 'com.azure:azure-identity:1.11.0'
@@ -40,7 +40,7 @@ Add the dependency in `dependencies` in pom.xml
com.microsoft.graph
microsoft-graph-core
- 3.6.3
+ 3.6.4
com.azure
diff --git a/android/build.gradle b/android/build.gradle
index 4821bb370..175e29751 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -6,7 +6,7 @@ buildscript {
dependencies {
classpath "com.gradle:gradle-enterprise-gradle-plugin:3.19.2"
- classpath "com.android.tools.build:gradle:8.10.1"
+ classpath "com.android.tools.build:gradle:8.11.0"
classpath "com.github.ben-manes:gradle-versions-plugin:0.52.0"
}
}
diff --git a/build.gradle b/build.gradle
index 85cba9289..f71ef6189 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ plugins {
id 'maven-publish'
id 'signing'
id 'jacoco'
- id 'com.github.spotbugs' version '6.2.0'
+ id 'com.github.spotbugs' version '6.2.1'
id "org.sonarqube" version "6.2.0.5505"
}
diff --git a/gradle.properties b/gradle.properties
index 97f5d5db2..f038876fc 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -30,7 +30,7 @@ mavenMajorVersion = 3
mavenMinorVersion = 6
# x-release-please-end
# x-release-please-start-patch
-mavenPatchVersion = 3
+mavenPatchVersion = 4
# x-release-please-end
mavenArtifactSuffix =
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index 8712ad006..d41fb6bd2 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -1,6 +1,6 @@
dependencies {
// Use JUnit test framework
- testImplementation 'org.junit.jupiter:junit-jupiter:5.13.1'
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.13.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.mockito:mockito-core:5.18.0'
testImplementation 'io.opentelemetry:opentelemetry-api:1.51.0'
@@ -18,11 +18,11 @@ dependencies {
api 'com.squareup.okhttp3:okhttp:4.12.0'
api 'com.azure:azure-core:1.54.1'
- api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.8.4'
- api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.8.4'
- implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.8.4'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.8.4'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.8.4'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.8.4'
- implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.8.4'
+ api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.8.7'
+ api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.8.7'
+ implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.8.7'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.8.7'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.8.7'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.8.7'
+ implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.8.7'
}
diff --git a/pom.xml b/pom.xml
index f4d6ea1c0..f22ac1911 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
com.microsoft.graph
microsoft-graph-core
- 3.6.3
+ 3.6.4
pom
@@ -32,18 +32,18 @@
com.azure
azure-core
- 1.55.4
+ 1.55.5
org.junit.jupiter
junit-jupiter-api
- 5.13.1
+ 5.13.2
test
org.junit.jupiter
junit-jupiter-params
- 5.13.1
+ 5.13.2
test
diff --git a/src/main/java/com/microsoft/graph/core/CoreConstants.java b/src/main/java/com/microsoft/graph/core/CoreConstants.java
index 0d3388fef..b7efb07bb 100644
--- a/src/main/java/com/microsoft/graph/core/CoreConstants.java
+++ b/src/main/java/com/microsoft/graph/core/CoreConstants.java
@@ -19,7 +19,7 @@ private static class VersionValues {
private static final int MINOR = 6;
// x-release-please-end
// x-release-please-start-patch
- private static final int PATCH = 3;
+ private static final int PATCH = 4;
// x-release-please-end
}
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 eec1e05fe..f8a45a65f 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,20 @@
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 com.microsoft.graph.core.ErrorConstants;
import com.microsoft.graph.core.exceptions.ClientException;
import com.microsoft.graph.core.models.IProgressCallback;
@@ -18,19 +33,10 @@
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;
+import okhttp3.OkHttpClient;
/**
* Task for uploading large files including pausing and resuming.
@@ -274,8 +280,15 @@ private long nextSliceSize(long rangeBegin, long rangeEnd) {
}
private byte[] chunkInputStream(InputStream stream, int length) throws IOException {
byte[] buffer = new byte[length];
- int lengthAssert = stream.read(buffer);
- assert lengthAssert == length;
+ int totalRead = 0;
+ while (totalRead < length) {
+ int bytesRead = stream.read(buffer, totalRead, length - totalRead);
+ if (bytesRead == -1) {
+ // End of stream reached
+ break;
+ }
+ totalRead += bytesRead;
+ }
return buffer;
}
}
diff --git a/src/test/java/com/microsoft/graph/core/tasks/LargeFileUploadTest.java b/src/test/java/com/microsoft/graph/core/tasks/LargeFileUploadTest.java
index 5f50476a3..26eacec54 100644
--- a/src/test/java/com/microsoft/graph/core/tasks/LargeFileUploadTest.java
+++ b/src/test/java/com/microsoft/graph/core/tasks/LargeFileUploadTest.java
@@ -5,9 +5,14 @@
import com.microsoft.graph.core.models.UploadSession;
import com.microsoft.kiota.authentication.AuthenticationProvider;
import com.microsoft.kiota.http.OkHttpRequestAdapter;
+
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.doReturn;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.mockito.ArgumentCaptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -17,6 +22,10 @@
import java.util.ArrayList;
import java.util.Arrays;
+import org.mockito.internal.matchers.Any;
+
+import com.microsoft.graph.core.models.UploadResult;
+
class LargeFileUploadTest {
final OkHttpRequestAdapter adapter = new OkHttpRequestAdapter(mock(AuthenticationProvider.class));
@@ -106,4 +115,59 @@ void BreakStreamIntoCorrectRanges() throws IOException, NoSuchFieldException, Il
assertEquals(size%maxSliceSize, lastSlice.getRangeLength());
assertEquals(size-1, lastSlice.getRangeEnd());
}
+ // Test for chunkInputStream method with a 5MB file
+ @Test
+ void uploads5MBFileSuccessfully() throws Exception {
+ // Arrange
+ UploadSession session = new UploadSession();
+ session.setNextExpectedRanges(Arrays.asList("0-"));
+ session.setUploadUrl("http://localhost");
+ session.setExpirationDateTime(OffsetDateTime.now().plusHours(1));
+
+ // 5MB file
+ byte[] data = new byte[5 * 1024 * 1024];
+ for (int i = 0; i < data.length; i++) {
+ data[i] = (byte)(i % 256);
+ }
+ ByteArrayInputStream stream = new ByteArrayInputStream(data);
+ int size = stream.available();
+
+ // Create a real task to get the real builder(s)
+ LargeFileUploadTask realTask = new LargeFileUploadTask<>(adapter, session, stream, size, TestDriveItem::createFromDiscriminatorValue);
+ var realBuilders = realTask.getUploadSliceRequests();
+
+ // Spy the builder(s) and mock put()
+ ArrayList> spyBuilders = new ArrayList<>();
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ByteArrayInputStream.class);
+
+ for (UploadSliceRequestBuilder builder : realBuilders) {
+ UploadSliceRequestBuilder spyBuilder = spy(builder);
+ UploadResult mockResult = new UploadResult<>();
+ TestDriveItem item = new TestDriveItem();
+ item.size = data.length;
+ mockResult.itemResponse = item;
+ doReturn(mockResult).when(spyBuilder).put(captor.capture());
+ spyBuilders.add(spyBuilder);
+ }
+
+ // Subclass LargeFileUploadTask to inject our spy builders
+ LargeFileUploadTask task = new LargeFileUploadTask<>(adapter, session, stream, size, TestDriveItem::createFromDiscriminatorValue) {
+ @Override
+ protected java.util.List> getUploadSliceRequests() {
+ return spyBuilders;
+ }
+ };
+
+ // Act
+ task.upload(3, null);
+
+ // Verify the chunkStream content
+ ByteArrayInputStream capturedStream = captor.getValue();
+ byte[] capturedBytes = new byte[data.length];
+ int read = capturedStream.read(capturedBytes);
+ assertEquals(data.length, read, "Should read all bytes from chunkStream");
+ for (int i = 0; i < data.length; i++) {
+ assertEquals(data[i], capturedBytes[i], "Byte at position " + i + " should match original data");
+ }
+ }
}