diff --git a/.github/workflows/build-dependent-std-libs.yml b/.github/workflows/build-dependent-std-libs.yml index 4980bf3..c95a98d 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/.github/workflows/build-timestamped-master.yml b/.github/workflows/build-timestamped-master.yml index fc41ddb..f713d94 100644 --- a/.github/workflows/build-timestamped-master.yml +++ b/.github/workflows/build-timestamped-master.yml @@ -13,5 +13,5 @@ jobs: call_workflow: name: Run Build Workflow if: ${{ github.repository_owner == 'ballerina-platform' }} - uses: ballerina-platform/ballerina-library/.github/workflows/build-timestamp-master-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/build-timestamp-master-template.yml@java21 secrets: inherit diff --git a/.github/workflows/build-with-bal-test-graalvm.yml b/.github/workflows/build-with-bal-test-graalvm.yml index 82d61b0..9d358de 100644 --- a/.github/workflows/build-with-bal-test-graalvm.yml +++ b/.github/workflows/build-with-bal-test-graalvm.yml @@ -30,7 +30,7 @@ jobs: call_stdlib_workflow: name: Run StdLib Workflow if: ${{ github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository_owner == 'ballerina-platform') }} - uses: ballerina-platform/ballerina-library/.github/workflows/build-with-bal-test-graalvm-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/build-with-bal-test-graalvm-template.yml@java21 with: lang_tag: ${{ inputs.lang_tag }} lang_version: ${{ inputs.lang_version }} diff --git a/.github/workflows/central-publish.yml b/.github/workflows/central-publish.yml index 457b7c9..4380fac 100644 --- a/.github/workflows/central-publish.yml +++ b/.github/workflows/central-publish.yml @@ -15,7 +15,7 @@ jobs: call_workflow: name: Run Central Publish Workflow if: ${{ github.repository_owner == 'ballerina-platform' }} - uses: ballerina-platform/ballerina-library/.github/workflows/central-publish-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/central-publish-template.yml@java21 secrets: inherit with: environment: ${{ github.event.inputs.environment }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index b336e44..760b569 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -9,7 +9,7 @@ jobs: call_workflow: name: Run Release Workflow if: ${{ github.repository_owner == 'ballerina-platform' }} - uses: ballerina-platform/ballerina-library/.github/workflows/release-package-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/release-package-template.yml@java21 secrets: inherit with: package-name: mime diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index dbbc163..806bcb0 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -6,5 +6,5 @@ jobs: call_workflow: name: Run PR Build Workflow if: ${{ github.repository_owner == 'ballerina-platform' }} - uses: ballerina-platform/ballerina-library/.github/workflows/pull-request-build-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/pull-request-build-template.yml@java21 secrets: inherit diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml index 2f7999d..684db29 100644 --- a/.github/workflows/trivy-scan.yml +++ b/.github/workflows/trivy-scan.yml @@ -9,5 +9,5 @@ jobs: call_workflow: name: Run Trivy Scan Workflow if: ${{ github.repository_owner == 'ballerina-platform' }} - uses: ballerina-platform/ballerina-library/.github/workflows/trivy-scan-template.yml@main + uses: ballerina-platform/ballerina-library/.github/workflows/trivy-scan-template.yml@java21 secrets: inherit diff --git a/README.md b/README.md index 9b6e90a..c2fd568 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 95022eb..81ef1a6 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.0" path = "../native/build/libs/mime-native-2.10.0.jar" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../test-utils/build/libs/mime-test-utils-2.10.0.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 9dc6481..912bd1b 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 48514a9..0e250b9 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 58f80af..dd743bf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,21 @@ org.gradle.caching=true group=io.ballerina.stdlib version=2.10.1-SNAPSHOT -ballerinaLangVersion=2201.10.0 +ballerinaLangVersion=2201.10.0-20241007-143200-6b69ca80 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.3 mockitoVersion=5.3.1 -stdlibIoVersion=1.6.0 -stdlibLogVersion=2.10.0 -observeVersion=1.3.0 -observeInternalVersion=1.3.0 +stdlibIoVersion=1.6.2-20240928-084100-656404f +stdlibLogVersion=2.10.1-20240930-154200-5ab2aa4 +observeVersion=1.3.1-20241007-161000-645452d +observeInternalVersion=1.3.1-20241007-182700-a5f77a1 diff --git a/native/build.gradle b/native/build.gradle index 82d3da4..30dd21c 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 a101286..95b6d81 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().call(iteratorObj, BYTE_STREAM_NEXT_FUNC); + 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,34 @@ 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 { + handleEventPanic(eventStreamWriter, env.getRuntime().call(eventStreamWriter, WRITE_EVENT_STREAM_METHOD)); + } catch (BError error) { + handleEventPanic(eventStreamWriter, error); + } catch (Throwable throwable) { + handleEventPanic(eventStreamWriter, ErrorCreator.createError(throwable)); + } + } + + public static void handleEventPanic(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) {