diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml
index 73481b3f68564..ecf8041030041 100755
--- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml
+++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml
@@ -23,12 +23,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
index 67e2613f1df90..3726620b1b49c 100755
--- a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
+++ b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
@@ -661,10 +661,10 @@
-
-
-
-
+
+
+
+
diff --git a/sdk/core/azure-core-jackson-tests/README.md b/sdk/core/azure-core-jackson-tests/README.md
index 6ea03171c25b3..c95771c8ca704 100644
--- a/sdk/core/azure-core-jackson-tests/README.md
+++ b/sdk/core/azure-core-jackson-tests/README.md
@@ -4,7 +4,9 @@ Azure Core Jackson Tests is a test package that tests `azure-core` library again
## Getting started
-This package is intended to run in Live Test Azure Pipeline (`java - core - test`) under `jackson_versions` test name), but you can run it locally by setting `AZURE_CORE_TEST_JACKSON_VERSION` environment variable.
+This package is intended to run in Live Test Azure Pipeline (`java - core - test`) under `jackson_supported_versions` and
+`jackson_unsupported_versions` test name), but you can run it locally by setting `AZURE_CORE_TEST_SUPPORTED_JACKSON_VERSION`
+or `AZURE_CORE_TEST_UNSUPPORTED_JACKSON_VERSION` environment variables.
## Key concepts
@@ -15,14 +17,14 @@ Here's how you can test arbitrary Jackson version from `azure-core-jackson-tests
Windows:
```powershell
-PS> $env:AZURE_CORE_TEST_JACKSON_VERSION="2.12.1"
+PS> $env:AZURE_CORE_TEST_SUPPORTED_JACKSON_VERSION="2.12.1"
PS> mvn test
```
Linux:
```bash
-$ export AZURE_CORE_TEST_JACKSON_VERSION="2.12.2"
+$ export AZURE_CORE_TEST_SUPPORTED_JACKSON_VERSION="2.12.2"
$ mvn test
```
diff --git a/sdk/core/azure-core-jackson-tests/pom.xml b/sdk/core/azure-core-jackson-tests/pom.xml
index 7ac3e1aadcc17..323cc7454c5c5 100644
--- a/sdk/core/azure-core-jackson-tests/pom.xml
+++ b/sdk/core/azure-core-jackson-tests/pom.xml
@@ -55,6 +55,7 @@
com.azure
azure-core
1.21.0-beta.1
+ test
@@ -159,40 +160,34 @@
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.0.0-M3
-
-
- com.azure:azure-core
-
-
-
- **/RestProxyXMLTests.java
-
-
-
-
-
-
- java-lts
+ default
- [11,)
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M3
+
+ true
+
+
+
+
+
- jackson-version-test-matrix
+ jackson-supported-version-test-matrix
- env.AZURE_CORE_TEST_JACKSON_VERSION
+ env.AZURE_CORE_TEST_SUPPORTED_JACKSON_VERSION
- ${env.AZURE_CORE_TEST_JACKSON_VERSION}
+ ${env.AZURE_CORE_TEST_SUPPORTED_JACKSON_VERSION}
@@ -226,8 +221,85 @@
${jackson.version}
test
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M3
+
+
+ com.azure:azure-core
+
+
+
+ **/RestProxyXMLTests.java
+ **/UnsupportedJacksonVersionsTests.java
+
+
+
+
+
+
+
+ jackson-unsupported-version-test
+
+ env.AZURE_CORE_TEST_UNSUPPORTED_JACKSON_VERSION
+
+
+ ${env.AZURE_CORE_TEST_UNSUPPORTED_JACKSON_VERSION}
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ ${jackson.version}
+ test
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+ test
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+ test
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson.version}
+ test
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson.version}
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M3
+
+
+ **/UnsupportedJacksonVersionsTests.java
+
+
+
+
+
+
diff --git a/sdk/core/azure-core-jackson-tests/src/test/java/com/azure/core/implementation/jackson/UnsupportedJacksonVersionsTests.java b/sdk/core/azure-core-jackson-tests/src/test/java/com/azure/core/implementation/jackson/UnsupportedJacksonVersionsTests.java
new file mode 100644
index 0000000000000..f4ee0632b536c
--- /dev/null
+++ b/sdk/core/azure-core-jackson-tests/src/test/java/com/azure/core/implementation/jackson/UnsupportedJacksonVersionsTests.java
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.implementation.jackson;
+
+import com.azure.core.util.CoreUtils;
+import com.azure.core.util.serializer.JacksonAdapter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class UnsupportedJacksonVersionsTests {
+ @Test
+ public void testUnsupportedVersion() {
+ String jacksonVersionString = ObjectMapper.class.getPackage().getImplementationVersion();
+ String azureCoreVersion = CoreUtils
+ .getProperties("azure-core.properties")
+ .getOrDefault("version", null);
+
+ JacksonVersion version = JacksonVersion.getInstance();
+ String helpInfo = version.getHelpInfo();
+ assertTrue(helpInfo.contains("jackson-annotations=" + jacksonVersionString));
+ assertTrue(helpInfo.contains("jackson-core=" + jacksonVersionString));
+ assertTrue(helpInfo.contains("jackson-databind=" + jacksonVersionString));
+ assertTrue(helpInfo.contains("jackson-dataformat-xml=" + jacksonVersionString));
+ assertTrue(helpInfo.contains("jackson-datatype-jsr310=" + jacksonVersionString));
+ assertTrue(helpInfo.contains("azure-core=" + azureCoreVersion));
+
+ Error error = assertThrows(Error.class, () -> new JacksonAdapter());
+ assertTrue(error.getMessage().contains(helpInfo));
+ }
+}
diff --git a/sdk/core/azure-core/pom.xml b/sdk/core/azure-core/pom.xml
index 22c75d3a1bcf5..6dcf854e48651 100644
--- a/sdk/core/azure-core/pom.xml
+++ b/sdk/core/azure-core/pom.xml
@@ -269,6 +269,7 @@
--add-opens com.azure.core/com.azure.core.implementation.models.jsonflatten=com.fasterxml.jackson.databind
--add-opens com.azure.core/com.azure.core.implementation.models.jsonflatten=ALL-UNNAMED
--add-opens com.azure.core/com.azure.core.implementation.serializer=ALL-UNNAMED
+ --add-opens com.azure.core/com.azure.core.implementation.jackson=ALL-UNNAMED
--add-opens com.azure.core/com.azure.core.models=ALL-UNNAMED
--add-opens com.azure.core/com.azure.core.util=ALL-UNNAMED
--add-opens com.azure.core/com.azure.core.util.logging=ALL-UNNAMED
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/http/policy/HttpLoggingPolicy.java b/sdk/core/azure-core/src/main/java/com/azure/core/http/policy/HttpLoggingPolicy.java
index e18917da93c62..6a1f9c9812060 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/http/policy/HttpLoggingPolicy.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/http/policy/HttpLoggingPolicy.java
@@ -11,13 +11,12 @@
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import com.azure.core.implementation.http.HttpPipelineCallContextHelper;
+import com.azure.core.implementation.jackson.ObjectMapperShim;
import com.azure.core.util.Context;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.UrlBuilder;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.logging.LogLevel;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
import reactor.core.publisher.Mono;
import java.io.ByteArrayOutputStream;
@@ -37,7 +36,7 @@
* The pipeline policy that handles logging of HTTP requests and responses.
*/
public class HttpLoggingPolicy implements HttpPipelinePolicy {
- private static final ObjectMapper PRETTY_PRINTER = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
+ private static final ObjectMapperShim PRETTY_PRINTER = ObjectMapperShim.createPrettyPrintMapper();
private static final int MAX_BODY_LOG_SIZE = 1024 * 16;
private static final String REDACTED_PLACEHOLDER = "REDACTED";
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/SemanticVersion.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/SemanticVersion.java
new file mode 100644
index 0000000000000..30cb2dbbe5f15
--- /dev/null
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/SemanticVersion.java
@@ -0,0 +1,257 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.implementation;
+
+import com.azure.core.util.CoreUtils;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * Implements lightweight semantic version based on https://semver.org/ for internal use.
+ */
+public final class SemanticVersion implements Comparable {
+
+ /**
+ * Represents unknown version - either invalid or missing.
+ */
+ public static final String UNKNOWN_VERSION = "unknown";
+
+ private final int major;
+ private final int minor;
+ private final int patch;
+ private final String prerelease;
+ private final String versionString;
+
+ /**
+ * Returns implementation version of the package for given class. If version can't be retrieved or parsed, returns invalid version.
+ *
+ * @param className - class name to get package version of.
+ * @return parsed {@link SemanticVersion} or invalid one.
+ */
+ public static SemanticVersion getPackageVersionForClass(String className) {
+ try {
+ return getPackageVersion(Class.forName(className));
+ } catch (Throwable e) {
+ return SemanticVersion.createInvalid();
+ }
+ }
+
+ /**
+ * Parses semver 2.0.0 string. If version can't be retrieved or parsed, returns invalid version.
+ *
+ * @param version to parse.
+ * @return parsed {@link SemanticVersion} or invalid one.
+ */
+ public static SemanticVersion parse(String version) {
+ Objects.requireNonNull(version, "'version' cannot be null.");
+ String[] parts = version.split("\\.");
+ if (parts.length < 3) {
+ return createInvalid(version);
+ }
+
+ int majorDotIdx = version.indexOf('.');
+ int minorDotIdx = version.indexOf('.', majorDotIdx + 1);
+ if (majorDotIdx < 0 || minorDotIdx < 0) {
+ return createInvalid(version);
+ }
+
+ int patchEndIdx = minorDotIdx + 1;
+ while (patchEndIdx < version.length()) {
+ Character ch = version.charAt(patchEndIdx);
+
+ // accommodate common broken semantic versions (e.g. 1.2.3.4)
+ if (ch == '.' || ch == '-' || ch == '+') {
+ break;
+ }
+
+ patchEndIdx++;
+ }
+
+ int extEndIdx = version.indexOf('+', patchEndIdx);
+ if (extEndIdx < 0) {
+ extEndIdx = version.length();
+ }
+
+ try {
+ Integer major = Integer.valueOf(version.substring(0, majorDotIdx));
+ Integer minor = Integer.valueOf(version.substring(majorDotIdx + 1, minorDotIdx));
+ Integer patch = Integer.valueOf(version.substring(minorDotIdx + 1, patchEndIdx));
+
+ String prerelease = (patchEndIdx == extEndIdx) ? "" : version.substring(patchEndIdx + 1, extEndIdx);
+ return new SemanticVersion(major, minor, patch, prerelease, version);
+ } catch (Throwable ex) {
+ return createInvalid(version);
+ }
+ }
+
+ /**
+ * Returns implementation version of the package for given class.
+ *
+ * @param clazz - class to get package version of.
+ * @return parsed {@link SemanticVersion} or invalid one.
+ */
+ private static SemanticVersion getPackageVersion(Class> clazz) {
+ Objects.requireNonNull(clazz, "'clazz' cannot be null.");
+ if (clazz.getPackage() == null) {
+ return createInvalid();
+ }
+
+ String versionStr = clazz.getPackage().getImplementationVersion();
+
+ if (versionStr != null) {
+ return parse(versionStr);
+ }
+
+ // if versionStr is null, try loading the version from the manifest in the jar file
+ JarFile jar = null;
+ try {
+ jar = new JarFile(clazz.getProtectionDomain().getCodeSource().getLocation().getFile());
+ Manifest manifest = jar.getManifest();
+ versionStr = manifest.getMainAttributes().getValue("Implementation-Version");
+ if (versionStr == null) {
+ versionStr = manifest.getMainAttributes().getValue("Bundle-Version");
+ }
+ return parse(versionStr);
+ } catch (Throwable t) {
+ return createInvalid();
+ } finally {
+ if (jar != null) {
+ try {
+ jar.close();
+ } catch (IOException e) {
+ // ignored
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates invalid semantic version.
+ * @return instance of invalid semantic version.
+ */
+ public static SemanticVersion createInvalid() {
+ return createInvalid(UNKNOWN_VERSION);
+ }
+
+ /**
+ * Creates invalid semantic version.
+ */
+ private static SemanticVersion createInvalid(String version) {
+ return new SemanticVersion(-1, -1, -1, null, version);
+ }
+
+ /**
+ * Creates semantic version.
+ *
+ * @param major major version.
+ * @param minor minor version.
+ * @param patch patch version.
+ * @param prerelease extensions (including '-' or '+' separator after patch).
+ * @param versionString full version string.
+ */
+ SemanticVersion(int major, int minor, int patch, String prerelease, String versionString) {
+ Objects.requireNonNull(versionString, "'versionString' cannot be null.");
+ this.major = major;
+ this.minor = minor;
+ this.patch = patch;
+ this.prerelease = prerelease;
+ this.versionString = versionString;
+ }
+
+ /**
+ * Returns full version string that was used to create this {@code SemanticVersion}
+ *
+ * @return original version string.
+ */
+ public String getVersionString() {
+ return versionString;
+ }
+
+ /**
+ * Returns major version component or -1 for invalid version.
+ *
+ * @return major version.
+ */
+ public int getMajorVersion() {
+ return major;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(SemanticVersion other) {
+ if (this == other) {
+ return 0;
+ }
+
+ if (other == null) {
+ return -1;
+ }
+
+ if (major != other.major) {
+ return major > other.major ? 1 : -1;
+ }
+
+ if (minor != other.minor) {
+ return minor > other.minor ? 1 : -1;
+ }
+
+ if (patch != other.patch) {
+ return patch > other.patch ? 1 : -1;
+ }
+
+ if (CoreUtils.isNullOrEmpty(prerelease)) {
+ return CoreUtils.isNullOrEmpty(other.prerelease) ? 0 : 1;
+ }
+
+ if (CoreUtils.isNullOrEmpty(other.prerelease)) {
+ return -1;
+ }
+
+ return prerelease.compareTo(other.prerelease);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof SemanticVersion)) {
+ return false;
+ }
+
+ SemanticVersion otherVer = (SemanticVersion) other;
+
+ return versionString.equals(otherVer.versionString);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return versionString.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return versionString;
+ }
+
+ /**
+ * Returns flag indicating if version is valid.
+ *
+ * @return true if version is valid, false otherwise.
+ */
+ public boolean isValid() {
+ return this.major >= 0;
+ }
+}
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesDeserializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesDeserializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesDeserializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesDeserializer.java
index b48fc265040ab..028091c91df5a 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesDeserializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesDeserializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.annotation.JsonFlatten;
import com.azure.core.implementation.TypeUtil;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesSerializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesSerializer.java
index 942b28cf89961..356e2b99ce49c 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/AdditionalPropertiesSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/AdditionalPropertiesSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.implementation.TypeUtil;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/Base64UrlSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/Base64UrlSerializer.java
similarity index 95%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/Base64UrlSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/Base64UrlSerializer.java
index fbdfd842a32d2..e6a4b4d8f4374 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/Base64UrlSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/Base64UrlSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.util.Base64Url;
import com.fasterxml.jackson.core.JsonGenerator;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/ByteArraySerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/ByteArraySerializer.java
similarity index 96%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/ByteArraySerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/ByteArraySerializer.java
index 9d821c0a5cc99..794e16a94b4ca 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/ByteArraySerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/ByteArraySerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeDeserializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeDeserializer.java
similarity index 97%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeDeserializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeDeserializer.java
index b7570318675be..5bda3008e656c 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeDeserializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeDeserializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeRfc1123Serializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeRfc1123Serializer.java
similarity index 96%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeRfc1123Serializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeRfc1123Serializer.java
index 78a451e9c2955..a09370236b90e 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeRfc1123Serializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeRfc1123Serializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.util.DateTimeRfc1123;
import com.fasterxml.jackson.core.JsonGenerator;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeSerializer.java
similarity index 97%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeSerializer.java
index 6a5851f089c6d..ae6db32f5213a 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DateTimeSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DateTimeSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DurationSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DurationSerializer.java
similarity index 98%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DurationSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DurationSerializer.java
index faa6448430bc0..0ea148a8dd79a 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/DurationSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/DurationSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningDeserializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningDeserializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningDeserializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningDeserializer.java
index a2ea39707baf1..dd60f00072659 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningDeserializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningDeserializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.annotation.JsonFlatten;
import com.azure.core.implementation.TypeUtil;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningSerializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningSerializer.java
index 80ae70a51bb3a..1a667902da729 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/FlatteningSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/FlatteningSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.annotation.JsonFlatten;
import com.azure.core.util.ExpandableStringEnum;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonDeserializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonDeserializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonDeserializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonDeserializer.java
index d4ea7a3fa50cc..fbcb98bdb81b1 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonDeserializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonDeserializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.models.GeoBoundingBox;
import com.azure.core.models.GeoCollection;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonSerializer.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonSerializer.java
similarity index 99%
rename from sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonSerializer.java
rename to sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonSerializer.java
index 207b8aa2907a7..cf1072ecd4e98 100644
--- a/sdk/core/azure-core/src/main/java/com/azure/core/util/serializer/GeoJsonSerializer.java
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/GeoJsonSerializer.java
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-package com.azure.core.util.serializer;
+package com.azure.core.implementation.jackson;
import com.azure.core.implementation.GeoObjectHelper;
import com.azure.core.models.GeoBoundingBox;
diff --git a/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/HeaderCollectionHandler.java b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/HeaderCollectionHandler.java
new file mode 100644
index 0000000000000..a6a2cfa6a3a3c
--- /dev/null
+++ b/sdk/core/azure-core/src/main/java/com/azure/core/implementation/jackson/HeaderCollectionHandler.java
@@ -0,0 +1,154 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.core.implementation.jackson;
+
+import com.azure.core.implementation.ReflectionUtils;
+import com.azure.core.util.logging.ClientLogger;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+
+/*
+ * Internal helper class that helps manage converting headers into their header collection.
+ */
+final class HeaderCollectionHandler {
+ private static final int CACHE_SIZE_LIMIT = 10000;
+ private static final Map FIELD_TO_SETTER_CACHE = new ConcurrentHashMap<>();
+ private final String prefix;
+ private final int prefixLength;
+ private final Map values;
+ private final Field declaringField;
+
+ HeaderCollectionHandler(String prefix, Field declaringField) {
+ this.prefix = prefix;
+ this.prefixLength = prefix.length();
+ this.values = new HashMap<>();
+ this.declaringField = declaringField;
+ }
+
+ boolean headerStartsWithPrefix(String headerName) {
+ return headerName.startsWith(prefix);
+ }
+
+ void addHeader(String headerName, String headerValue) {
+ values.put(headerName.substring(prefixLength), headerValue);
+ }
+
+ @SuppressWarnings("deprecation")
+ void injectValuesIntoDeclaringField(Object deserializedHeaders, ClientLogger logger) {
+ /*
+ * First check if the deserialized headers type has a public setter.
+ */
+ if (usePublicSetter(deserializedHeaders, logger)) {
+ return;
+ }
+
+ /*
+ * Otherwise, fallback to setting the field directly.
+ */
+ final boolean declaredFieldAccessibleBackup = declaringField.isAccessible();
+ try {
+ if (!declaredFieldAccessibleBackup) {
+ AccessController.doPrivileged((PrivilegedAction