diff --git a/.github/workflows/build-dependent-std-libs.yml b/.github/workflows/build-dependent-std-libs.yml index 4980bf3b..c95a98da 100644 --- a/.github/workflows/build-dependent-std-libs.yml +++ b/.github/workflows/build-dependent-std-libs.yml @@ -26,11 +26,11 @@ jobs: matrix: module: ${{ fromJson(inputs.ballerina_modules) }} steps: - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: 17.0.7 + java-version: 21 - name: Checkout module uses: actions/checkout@v3 diff --git a/README.md b/README.md index 9b6e90a0..c2fd5682 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ This repository only contains the source code for the package. ### Set up the prerequisites -1. Download and install Java SE Development Kit (JDK) version 17 (from one of the following locations). +1. Download and install Java SE Development Kit (JDK) version 21 (from one of the following locations). * [Oracle](https://www.oracle.com/java/technologies/downloads/) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 74348a7d..99f5fad3 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -9,26 +9,26 @@ icon = "icon.png" license = ["Apache-2.0"] distribution = "2201.10.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] groupId = "io.ballerina.stdlib" artifactId = "mime-native" version = "2.10.1" path = "../native/build/libs/mime-native-2.10.1.jar" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../test-utils/build/libs/mime-test-utils-2.10.1.jar" scope = "testOnly" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/mimepull-1.9.11.jar" groupId = "org.jvnet.mimepull" artifactId = "mimepull" version = "1.9.11" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/jakarta.activation-api-2.0.1.jar" groupId = "jakarta.activation" artifactId = "jakarta.activation-api" diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 9dc64815..912bd1bb 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -9,26 +9,26 @@ icon = "icon.png" license = ["Apache-2.0"] distribution = "2201.10.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] groupId = "io.ballerina.stdlib" artifactId = "mime-native" version = "@toml.version@" path = "../native/build/libs/mime-native-@project.version@.jar" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../test-utils/build/libs/mime-test-utils-@project.version@.jar" scope = "testOnly" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/mimepull-@mimepull.version@.jar" groupId = "org.jvnet.mimepull" artifactId = "mimepull" version = "@mimepull.version@" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/jakarta.activation-api-@jakarta.activation.version@.jar" groupId = "jakarta.activation" artifactId = "jakarta.activation-api" diff --git a/build.gradle b/build.gradle index 48514a98..0e250b96 100644 --- a/build.gradle +++ b/build.gradle @@ -16,10 +16,10 @@ */ plugins { - id "com.github.spotbugs" version "5.0.14" - id "com.github.johnrengelman.shadow" version "8.1.1" - id "de.undercouch.download" version "5.4.0" - id "net.researchgate.release" version "2.8.0" + id "com.github.spotbugs" version "${githubSpotbugsVersion}" + id "com.github.johnrengelman.shadow" version "${githubJohnrengelmanShadowVersion}" + id "de.undercouch.download" version "${underCouchDownloadVersion}" + id "net.researchgate.release" version "${researchgateReleaseVersion}" } ext.ballerinaLangVersion = project.ballerinaLangVersion diff --git a/gradle.properties b/gradle.properties index 9c42bbe4..8ac0ed3f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,21 @@ org.gradle.caching=true group=io.ballerina.stdlib version=2.10.2-SNAPSHOT -ballerinaLangVersion=2201.10.0 +ballerinaLangVersion=2201.11.0-20241112-214900-6b80ab87 mimepullVersion=1.9.11 puppycrawlCheckstyleVersion=10.12.0 +githubJohnrengelmanShadowVersion=8.1.1 +underCouchDownloadVersion=5.4.0 +researchgateReleaseVersion=2.8.0 +checkstyleToolVersion=10.12.0 +githubSpotbugsVersion=6.0.18 jakartaActivationVersion=2.0.1 testngVersion=7.6.1 ballerinaGradlePluginVersion=2.2.4 mockitoVersion=5.3.1 -stdlibIoVersion=1.6.0 -stdlibLogVersion=2.10.0 -observeVersion=1.3.0 -observeInternalVersion=1.3.0 +stdlibIoVersion=1.6.2-20241112-233100-995cf5f +stdlibLogVersion=2.10.1-20241113-120000-4577868 +observeVersion=1.4.0-20241113-092000-b83ae74 +observeInternalVersion=1.3.1-20241113-101700-265054d diff --git a/native/build.gradle b/native/build.gradle index 82d3da4b..30dd21c4 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -86,8 +86,11 @@ checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") checkstyleTest.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") spotbugsMain { - effort "max" - reportLevel "low" + def classLoader = plugins["com.github.spotbugs"].class.classLoader + def SpotBugsConfidence = classLoader.findLoadedClass("com.github.spotbugs.snom.Confidence") + def SpotBugsEffort = classLoader.findLoadedClass("com.github.spotbugs.snom.Effort") + effort = SpotBugsEffort.MAX + reportLevel = SpotBugsConfidence.LOW reportsDir = file("$project.buildDir/reports/spotbugs") reports { html.enabled true diff --git a/native/src/main/java/io/ballerina/stdlib/mime/util/EntityBodyHandler.java b/native/src/main/java/io/ballerina/stdlib/mime/util/EntityBodyHandler.java index a101286d..80829ede 100644 --- a/native/src/main/java/io/ballerina/stdlib/mime/util/EntityBodyHandler.java +++ b/native/src/main/java/io/ballerina/stdlib/mime/util/EntityBodyHandler.java @@ -19,7 +19,6 @@ package io.ballerina.stdlib.mime.util; import io.ballerina.runtime.api.Environment; -import io.ballerina.runtime.api.async.Callback; import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; @@ -48,8 +47,6 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import static io.ballerina.stdlib.mime.util.MimeConstants.BODY_PARTS; import static io.ballerina.stdlib.mime.util.MimeConstants.BYTE_STREAM_NEXT_FUNC; @@ -374,53 +371,44 @@ public static void writeByteStreamToOutputStream(Environment env, BObject entity BStream byteStream = EntityBodyHandler.getByteStream(entity); if (byteStream != null) { BObject iteratorObj = byteStream.getIteratorObj(); - CountDownLatch latch = new CountDownLatch(1); - writeContent(env, entity, outputStream, iteratorObj, latch); - try { - int timeout = 120; - boolean countDownReached = latch.await(timeout, TimeUnit.SECONDS); - if (!countDownReached) { - throw ErrorCreator.createError(StringUtils.fromString( - "Could not complete byte stream serialization within " + timeout + " seconds")); - } - } catch (InterruptedException e) { - log.warn("Interrupted before completing the content write"); - } + writeContent(env, entity, outputStream, iteratorObj); } } private static void writeContent(Environment env, BObject entity, OutputStream outputStream, - BObject iteratorObj, CountDownLatch latch) { - env.getRuntime().invokeMethodAsyncConcurrently(iteratorObj, BYTE_STREAM_NEXT_FUNC, null, null, new Callback() { - @Override - public void notifySuccess(Object result) { - if (result == null) { - entity.addNativeData(ENTITY_BYTE_STREAM, null); - latch.countDown(); - return; - } - if (result instanceof BError error) { - entity.addNativeData(ENTITY_BYTE_STREAM, null); - this.notifyFailure(error); - } - try { - writeContentPart((BMap) result, outputStream); - } catch (Exception e) { - latch.countDown(); - throw ErrorCreator.createError(StringUtils.fromString( - "Error occurred while writing the stream content: " - + MimeUtil.removeJavaExceptionPrefix(e.getMessage()))); - } - writeContent(env, entity, outputStream, iteratorObj, latch); - } + BObject iteratorObj) { + try { + Object result = env.getRuntime().callMethod(iteratorObj, BYTE_STREAM_NEXT_FUNC, null); + handleContentResult(env, entity, outputStream, result, iteratorObj); + } catch (BError error) { + handleContentPanic(error); + } catch (Throwable throwable) { + handleContentPanic(ErrorCreator.createError(throwable)); + } + } - @Override - public void notifyFailure(BError bError) { - latch.countDown(); - throw ErrorCreator.createError(StringUtils.fromString( - "Error occurred while streaming content: " + bError.getMessage())); - } - }, null, null, new Object[]{}); + public static void handleContentResult(Environment env, BObject entity, OutputStream outputStream, Object result, + BObject iteratorObj) { + if (result == null) { + entity.addNativeData(ENTITY_BYTE_STREAM, null); + return; + } + if (result instanceof BError error) { + entity.addNativeData(ENTITY_BYTE_STREAM, null); + handleContentPanic(error); + } + try { + writeContentPart((BMap) result, outputStream); + } catch (Exception e) { + throw ErrorCreator.createError(StringUtils.fromString("Error occurred while writing the stream content: " + + MimeUtil.removeJavaExceptionPrefix(e.getMessage()))); + } + writeContent(env, entity, outputStream, iteratorObj); + } + + public static void handleContentPanic(BError bError) { + throw ErrorCreator.createError(StringUtils.fromString("Error occurred while streaming content: " + + bError.getMessage())); } /** @@ -442,31 +430,35 @@ public static void writeEventStreamToOutputStream(Environment env, BObject entit } private static void writeEvent(Environment env, BObject eventStreamWriter) { - env.getRuntime().invokeMethodAsyncConcurrently(eventStreamWriter, WRITE_EVENT_STREAM_METHOD, null, null, - new Callback() { - @Override - public void notifySuccess(Object result) { - BObject entity = (BObject) eventStreamWriter.getNativeData(ENTITY); - OutputStream outputStream = (OutputStream) eventStreamWriter.getNativeData(OUTPUT_STREAM); - if (result == null) { - entity.addNativeData(ENTITY_BYTE_STREAM, null); - EntityBodyHandler.closeMessageOutputStream(outputStream); - return; - } - if (result instanceof BError error) { - entity.addNativeData(ENTITY_BYTE_STREAM, null); - throw error; - } - } - - @Override - public void notifyFailure(BError bError) { - OutputStream outputStream = (OutputStream) eventStreamWriter.getNativeData(OUTPUT_STREAM); - EntityBodyHandler.closeMessageOutputStream(outputStream); - throw ErrorCreator.createError(StringUtils.fromString( - "Error occurred while streaming content: " + bError.getMessage())); - } - }, null, null); + try { + handleEventResult(eventStreamWriter, env.getRuntime().callMethod(eventStreamWriter, + WRITE_EVENT_STREAM_METHOD, null)); + } catch (BError error) { + handleEventPanic(eventStreamWriter, error); + } catch (Throwable throwable) { + handleEventPanic(eventStreamWriter, ErrorCreator.createError(throwable)); + } + } + + public static void handleEventResult(BObject eventStreamWriter, Object result) { + BObject entity = (BObject) eventStreamWriter.getNativeData(ENTITY); + OutputStream outputStream = (OutputStream) eventStreamWriter.getNativeData(OUTPUT_STREAM); + if (result == null) { + entity.addNativeData(ENTITY_BYTE_STREAM, null); + EntityBodyHandler.closeMessageOutputStream(outputStream); + return; + } + if (result instanceof BError error) { + entity.addNativeData(ENTITY_BYTE_STREAM, null); + throw error; + } + } + + private static void handleEventPanic(BObject eventStreamWriter, BError bError) { + OutputStream outputStream = (OutputStream) eventStreamWriter.getNativeData(OUTPUT_STREAM); + EntityBodyHandler.closeMessageOutputStream(outputStream); + throw ErrorCreator.createError(StringUtils.fromString("Error occurred while streaming content: " + + bError.getMessage())); } private static void closeMessageOutputStream(OutputStream messageOutputStream) { diff --git a/native/src/main/java/io/ballerina/stdlib/mime/util/EntityHeaderHandler.java b/native/src/main/java/io/ballerina/stdlib/mime/util/EntityHeaderHandler.java index 880a2033..2ee73acc 100644 --- a/native/src/main/java/io/ballerina/stdlib/mime/util/EntityHeaderHandler.java +++ b/native/src/main/java/io/ballerina/stdlib/mime/util/EntityHeaderHandler.java @@ -18,10 +18,10 @@ package io.ballerina.stdlib.mime.util; -import io.ballerina.runtime.api.PredefinedTypes; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BMap; diff --git a/native/src/main/java/io/ballerina/stdlib/mime/util/HeaderUtil.java b/native/src/main/java/io/ballerina/stdlib/mime/util/HeaderUtil.java index cfb7d578..36645a7b 100644 --- a/native/src/main/java/io/ballerina/stdlib/mime/util/HeaderUtil.java +++ b/native/src/main/java/io/ballerina/stdlib/mime/util/HeaderUtil.java @@ -18,10 +18,10 @@ package io.ballerina.stdlib.mime.util; -import io.ballerina.runtime.api.PredefinedTypes; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BObject; diff --git a/native/src/main/java/io/ballerina/stdlib/mime/util/MimeUtil.java b/native/src/main/java/io/ballerina/stdlib/mime/util/MimeUtil.java index 2771dc96..ad53e505 100644 --- a/native/src/main/java/io/ballerina/stdlib/mime/util/MimeUtil.java +++ b/native/src/main/java/io/ballerina/stdlib/mime/util/MimeUtil.java @@ -19,12 +19,12 @@ package io.ballerina.stdlib.mime.util; import io.ballerina.runtime.api.Module; -import io.ballerina.runtime.api.PredefinedTypes; -import io.ballerina.runtime.api.TypeTags; import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; diff --git a/native/src/main/java/io/ballerina/stdlib/mime/util/MultipartDataSource.java b/native/src/main/java/io/ballerina/stdlib/mime/util/MultipartDataSource.java index 38b700d9..646d9b91 100644 --- a/native/src/main/java/io/ballerina/stdlib/mime/util/MultipartDataSource.java +++ b/native/src/main/java/io/ballerina/stdlib/mime/util/MultipartDataSource.java @@ -19,9 +19,9 @@ package io.ballerina.stdlib.mime.util; import io.ballerina.runtime.api.Environment; -import io.ballerina.runtime.api.PredefinedTypes; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BLink; diff --git a/native/src/test/java/io/ballerina/stdlib/mime/util/HeaderUtilTest.java b/native/src/test/java/io/ballerina/stdlib/mime/util/HeaderUtilTest.java index 11eaa3e4..fe63912f 100644 --- a/native/src/test/java/io/ballerina/stdlib/mime/util/HeaderUtilTest.java +++ b/native/src/test/java/io/ballerina/stdlib/mime/util/HeaderUtilTest.java @@ -18,10 +18,10 @@ package io.ballerina.stdlib.mime.util; -import io.ballerina.runtime.api.PredefinedTypes; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BObject; import io.ballerina.runtime.api.values.BString; diff --git a/native/src/test/java/io/ballerina/stdlib/mime/util/MimeUtilTest.java b/native/src/test/java/io/ballerina/stdlib/mime/util/MimeUtilTest.java index 2a6d7ae4..94ec7c1b 100644 --- a/native/src/test/java/io/ballerina/stdlib/mime/util/MimeUtilTest.java +++ b/native/src/test/java/io/ballerina/stdlib/mime/util/MimeUtilTest.java @@ -18,11 +18,11 @@ package io.ballerina.stdlib.mime.util; -import io.ballerina.runtime.api.PredefinedTypes; -import io.ballerina.runtime.api.TypeTags; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.PredefinedTypes; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BObject; import io.ballerina.runtime.api.values.BStreamingJson;