diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5ace4600 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 57cc4eec..7732559a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,19 +24,19 @@ jobs: name: Code Format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: jcheckstyle run: ./sbt jcheckStyle test_jdk21: name: Test JDK21 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '21' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk21-${{ hashFiles('**/*.sbt') }} @@ -49,12 +49,12 @@ jobs: name: Test JDK17 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '17' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk17-${{ hashFiles('**/*.sbt') }} @@ -67,12 +67,12 @@ jobs: name: Test JDK11 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '11' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk11-${{ hashFiles('**/*.sbt') }} @@ -85,12 +85,12 @@ jobs: name: Test JDK8 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: '8' - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.cache key: ${{ runner.os }}-jdk8-${{ hashFiles('**/*.sbt') }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d105d9d1..b214d8ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,16 +11,17 @@ jobs: name: Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags -f # Install OpenJDK 8 - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v4 with: # We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516 - java-version: adopt@1.8 + java-version: 8 + distribution: adopt - name: Setup GPG env: PGP_SECRET: ${{ secrets.PGP_SECRET }} diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index e244adfd..cbce4c14 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -16,14 +16,15 @@ jobs: name: Publish snapshots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 10000 # Fetch all tags so that sbt-dynver can find the previous release version - run: git fetch --tags - - uses: olafurpg/setup-scala@v10 + - uses: actions/setup-java@v4 with: - java-version: adopt@1.11 + java-version: 11 + distribution: adopt - name: Publish snapshots env: SONATYPE_USERNAME: '${{ secrets.SONATYPE_USER }}' diff --git a/build.sbt b/build.sbt index 3aa3c9c7..dc5a2c23 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ Global / concurrentRestrictions := Seq( Tags.limit(Tags.Test, 1) ) -val AIRFRAME_VERSION = "23.9.1" +val AIRFRAME_VERSION = "23.11.3" // Use dynamic snapshot version strings for non tagged versions ThisBuild / dynverSonatypeSnapshots := true @@ -109,7 +109,7 @@ lazy val msgpackJackson = "org.msgpack.jackson.dataformat" ), libraryDependencies ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.3", junitInterface, "org.apache.commons" % "commons-math3" % "3.6.1" % "test" ), diff --git a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java index 4cf789d9..72c26eca 100644 --- a/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java +++ b/msgpack-core/src/main/java/org/msgpack/core/MessagePacker.java @@ -774,10 +774,6 @@ else if (s.length() < (1 << 16)) { position += written; } else { - if (written >= (1L << 32)) { // this check does nothing because (1L << 32) is larger than Integer.MAX_VALUE - // this must not happen because s.length() is less than 2^16 and (2^16) * UTF_8_MAX_CHAR_SIZE is less than 2^32 - throw new IllegalArgumentException("Unexpected UTF-8 encoder state"); - } // move 2 bytes backward to expand 3-byte header region to 5 bytes buffer.putMessageBuffer(position + 5, buffer, position + 3, written); // write 3-byte header header diff --git a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java index 227c85d0..1891d9a7 100644 --- a/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java +++ b/msgpack-core/src/main/java/org/msgpack/value/impl/ImmutableTimestampValueImpl.java @@ -93,7 +93,7 @@ public byte[] getData() long sec = getEpochSecond(); int nsec = getNano(); if (sec >>> 34 == 0) { - long data64 = (nsec << 34) | sec; + long data64 = ((long) nsec << 34) | sec; if ((data64 & 0xffffffff00000000L) == 0L) { bytes = new byte[4]; MessageBuffer.wrap(bytes).putInt(0, (int) sec); diff --git a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala index 4f6949bd..c2993f96 100644 --- a/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala +++ b/msgpack-core/src/test/scala/org/msgpack/core/MessagePackTest.scala @@ -78,7 +78,7 @@ class MessagePackTest extends AirSpec with PropertyCheck with Benchmark { test("detect fixint values") { - for (i <- 0 until 0x79) { + for (i <- 0 until 0x7f) { Code.isPosFixInt(i.toByte) shouldBe true } diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index e91c6f8b..0156453e 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -64,10 +64,10 @@ Or more easily: ObjectMapper objectMapper = new MessagePackMapper(); ``` -We strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` if you serialize and/or deserialize BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. +We strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` if you serialize and/or deserialize BigInteger/BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); ``` ### Serialization/Deserialization of List @@ -232,10 +232,10 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Serialize and deserialize BigDecimal as str type internally in MessagePack format -`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` to internally handle BigDecimal values as String. +`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` to internally handle BigDecimal values as String. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); Pojo obj = new Pojo(); // This value is too large to be serialized as double @@ -245,10 +245,11 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(objectMapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} ``` -`MessagePackMapper#handleBigDecimalAsString()` is equivalent to the following configuration. +`MessagePackMapper#handleBigIntegerAndDecimalAsString()` is equivalent to the following configuration. ```java ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); objectMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); ``` diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java index 52af0372..144c8d1a 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.cfg.MapperBuilder; import java.math.BigDecimal; +import java.math.BigInteger; public class MessagePackMapper extends ObjectMapper { @@ -43,12 +44,23 @@ public MessagePackMapper(MessagePackFactory f) super(f); } + public MessagePackMapper handleBigIntegerAsString() + { + configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + return this; + } + public MessagePackMapper handleBigDecimalAsString() { configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); return this; } + public MessagePackMapper handleBigIntegerAndBigDecimalAsString() + { + return handleBigIntegerAsString().handleBigDecimalAsString(); + } + public static Builder builder() { return new Builder(new MessagePackMapper()); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java index 6dfd41cf..68721fce 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java @@ -15,30 +15,97 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.Test; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class MessagePackMapperTest { - static class Pojo + static class PojoWithBigInteger + { + public BigInteger value; + } + + static class PojoWithBigDecimal { public BigDecimal value; } - @Test - public void handleBigDecimalAsString() throws IOException + private void shouldFailToHandleBigInteger(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } + + private void shouldSuccessToHandleBigInteger(MessagePackMapper messagePackMapper) throws IOException { - MessagePackMapper mapper = new MessagePackMapper().handleBigDecimalAsString(); - Pojo obj = new Pojo(); + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigInteger deserialized = messagePackMapper.readValue(converted, PojoWithBigInteger.class); + assertEquals(obj.value, deserialized.value); + } + + private void shouldFailToHandleBigDecimal(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); obj.value = new BigDecimal("1234567890.98765432100"); - byte[] converted = mapper.writeValueAsBytes(obj); + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } - Pojo deserialized = mapper.readValue(converted, Pojo.class); + private void shouldSuccessToHandleBigDecimal(MessagePackMapper messagePackMapper) throws IOException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); + obj.value = new BigDecimal("1234567890.98765432100"); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigDecimal deserialized = messagePackMapper.readValue(converted, PojoWithBigDecimal.class); assertEquals(obj.value, deserialized.value); } + + @Test + public void handleBigIntegerAsString() throws IOException + { + shouldFailToHandleBigInteger(new MessagePackMapper()); + shouldSuccessToHandleBigInteger(new MessagePackMapper().handleBigIntegerAsString()); + } + + @Test + public void handleBigDecimalAsString() throws IOException + { + shouldFailToHandleBigDecimal(new MessagePackMapper()); + shouldSuccessToHandleBigDecimal(new MessagePackMapper().handleBigDecimalAsString()); + } + + @Test + public void handleBigIntegerAndBigDecimalAsString() throws IOException + { + MessagePackMapper messagePackMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); + shouldSuccessToHandleBigInteger(messagePackMapper); + shouldSuccessToHandleBigDecimal(messagePackMapper); + } } diff --git a/project/build.properties b/project/build.properties index 07960c01..d9282559 100755 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ -sbt.version=1.9.6 +sbt.version=1.9.7 diff --git a/project/plugins.sbt b/project/plugins.sbt index dd508b3b..ba0a0c26 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,10 +1,10 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") // TODO: Fixes jacoco error: // java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter //addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0") addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1") -addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.9.6") +addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.9.9") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2") addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1")