├── ballerina ├── tests │ ├── resources │ │ ├── empty.txt │ │ ├── csvResourceFileForUtils.csv │ │ ├── stringResourceFile2.txt │ │ ├── stringResourceFile1.txt │ │ ├── csvResourceFile2.csv │ │ ├── originalXmlContent.xml │ │ ├── expectedXmlCharsFile4.xml │ │ ├── expectedXmlCharsFile5.xml │ │ ├── csvResourceFileWithMissingFields.csv │ │ ├── expectedXmlCharsFile8.xml │ │ ├── csvResourceFile1.csv │ │ ├── csvResourceFileWithEmptyValues.csv │ │ ├── csvResourceFile1Shuffled.csv │ │ ├── expectedXmlCharsFile7.xml │ │ ├── csvResourceFile1WithMulltipleHeaders.csv │ │ └── expectedXmlCharsFile6.xml │ ├── test_constants.bal │ ├── open_io.bal │ └── conversion_io.bal ├── icon.png ├── CompilerPlugin.toml ├── init.bal ├── Ballerina.toml ├── channel.bal ├── read.bal ├── io_error.bal ├── options.bal ├── README.md ├── types.bal ├── constants.bal ├── writable_byte_channel.bal ├── line_stream.bal ├── file_byte_io.bal ├── csv_stream.bal ├── channel_byte_io.bal ├── block_stream.bal ├── writable_csv_channel.bal ├── Dependencies.toml ├── writable_record_channel.bal ├── string_reader.bal └── readable_record_channel.bal ├── native └── src │ ├── test │ ├── resources │ │ ├── datafiles │ │ │ └── io │ │ │ │ ├── text │ │ │ │ ├── emptyFile.txt │ │ │ │ ├── charfile.txt │ │ │ │ ├── utf8file.txt │ │ │ │ ├── corruptedText2 │ │ │ │ ├── longChars.txt │ │ │ │ ├── sequenceOfChars │ │ │ │ ├── corruptedText │ │ │ │ ├── person.properties │ │ │ │ └── longParagraph.txt │ │ │ │ ├── records │ │ │ │ ├── sample5d.csv │ │ │ │ ├── sample.csv │ │ │ │ ├── sample5.csv │ │ │ │ ├── sampleWithColon.txt │ │ │ │ ├── sample5b.csv │ │ │ │ ├── sample5d2.csv │ │ │ │ ├── sample3 │ │ │ │ ├── sample5R.csv │ │ │ │ ├── sampleTdf.tsv │ │ │ │ ├── sampleWithHeader.csv │ │ │ │ ├── sample5c.csv │ │ │ │ ├── sampleRfc.csv │ │ │ │ ├── sample6.csv │ │ │ │ ├── sample9.csv │ │ │ │ ├── sampleRef.csv │ │ │ │ ├── sampleRefE.csv │ │ │ │ ├── sample8.csv │ │ │ │ ├── sample2.csv │ │ │ │ ├── sample4.csv │ │ │ │ └── sample7.csv │ │ │ │ └── images │ │ │ │ └── ballerina.png │ │ └── testng.xml │ └── java │ │ └── io │ │ └── ballerina │ │ └── stdlib │ │ └── io │ │ ├── bytes │ │ └── ReadByteResult.java │ │ ├── MockByteChannel.java │ │ ├── channels │ │ ├── TempFileIOChannelTest.java │ │ ├── BlobIOChannelTest.java │ │ ├── FileIOChannelTest.java │ │ └── BlobChannelTest.java │ │ ├── util │ │ ├── Base64ByteChannelTest.java │ │ ├── JBallerinaTestInitializer.java │ │ ├── TestUtil.java │ │ ├── UtilsTest.java │ │ └── Base64WrapperTest.java │ │ ├── characters │ │ └── AsyncReadWriteTest.java │ │ └── records │ │ └── AsyncReadWriteTest.java │ └── main │ └── java │ ├── module-info.java │ └── io │ └── ballerina │ └── stdlib │ └── io │ ├── utils │ ├── BallerinaIOException.java │ ├── Base64Wrapper.java │ └── Base64ByteChannel.java │ ├── channels │ ├── base │ │ ├── data │ │ │ └── LongResult.java │ │ ├── Representation.java │ │ └── IOChannel.java │ ├── BlobIOChannel.java │ ├── TempFileIOChannel.java │ ├── FileIOChannel.java │ ├── AbstractNativeChannel.java │ └── BlobChannel.java │ ├── nativeimpl │ ├── ModuleUtils.java │ ├── WriteXml.java │ ├── ReadlnAny.java │ └── PrintUtils.java │ ├── readers │ └── CharacterChannelReader.java │ └── csv │ └── Format.java ├── .gitattributes ├── examples ├── salesforce │ ├── Config.toml │ ├── Ballerina.toml │ ├── resources │ │ └── data.csv │ ├── A Guildeline on Salesforce Bulk Processing.md │ └── main.bal ├── csv-processor │ ├── Ballerina.toml │ ├── A Guildeline on Processing CSV Files.md │ └── main.bal ├── bow │ ├── Ballerina.toml │ ├── A Guideline on Implementing Bag of Word Model Generator.md │ └── main.bal └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── load-tests └── csv_processor │ ├── src │ ├── Ballerina.toml │ ├── Cloud.toml │ └── app.bal │ ├── deployment │ ├── kustomization.yaml │ ├── deployment-patch.yaml │ └── ingress.yaml │ └── scripts │ └── run.sh ├── codecov.yml ├── compiler-plugin ├── src │ └── main │ │ ├── resources │ │ └── rules.json │ │ └── java │ │ ├── module-info.java │ │ └── io │ │ └── ballerina │ │ └── stdlib │ │ └── io │ │ └── compiler │ │ ├── staticcodeanalyzer │ │ ├── RuleFactory.java │ │ ├── IOCodeAnalyzer.java │ │ ├── RuleImpl.java │ │ └── IORule.java │ │ ├── IOCompilerPlugin.java │ │ └── Constants.java └── build.gradle ├── .github ├── pull_request_template.md ├── CODEOWNERS └── workflows │ ├── trivy-scan.yml │ ├── pull-request.yml │ ├── publish-release.yml │ ├── build-timestamped-master.yml │ ├── fossa_scan.yml │ ├── process-load-test-result.yml │ ├── central-publish.yml │ ├── trigger-load-tests.yml │ ├── build-with-bal-test-graalvm.yml │ └── update_specs.yml ├── compiler-plugin-tests └── src │ └── test │ └── resources │ ├── static_code_analyzer │ ├── ballerina_packages │ │ └── rule1 │ │ │ ├── Ballerina.toml │ │ │ └── main.bal │ └── expected_output │ │ └── rule1.json │ └── testng.xml ├── gradle.properties ├── .gitignore ├── spotbugs-exclude.xml ├── test-utils ├── src │ └── main │ │ └── java │ │ ├── module-info.java │ │ └── io │ │ └── ballerina │ │ └── stdlib │ │ └── io │ │ └── testutils │ │ ├── EnvironmentTestUtils.java │ │ ├── FileTestUtils.java │ │ └── PrintTestUtils.java └── build.gradle ├── settings.gradle ├── gradlew.bat └── changelog.md /ballerina/tests/resources/empty.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFileForUtils.csv: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/emptyFile.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/charfile.txt: -------------------------------------------------------------------------------- 1 | 123456 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/utf8file.txt: -------------------------------------------------------------------------------- 1 | aaabbNJ -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Ensure all Java files use LF. 2 | *.java eol=lf 3 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/corruptedText2: -------------------------------------------------------------------------------- 1 | �����a -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/longChars.txt: -------------------------------------------------------------------------------- 1 | NJabcNJff -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/sequenceOfChars: -------------------------------------------------------------------------------- 1 | 1234567 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/corruptedText: -------------------------------------------------------------------------------- 1 | �Test Curr ß � -------------------------------------------------------------------------------- /ballerina/tests/resources/stringResourceFile2.txt: -------------------------------------------------------------------------------- 1 | WSO2 2 | Google 3 | Microsoft 4 | Facebook 5 | Apple 6 | -------------------------------------------------------------------------------- /examples/salesforce/Config.toml: -------------------------------------------------------------------------------- 1 | BASE_URL="" 2 | SF_TOKEN="" 3 | -------------------------------------------------------------------------------- /ballerina/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ballerina-platform/module-ballerina-io/HEAD/ballerina/icon.png -------------------------------------------------------------------------------- /ballerina/tests/resources/stringResourceFile1.txt: -------------------------------------------------------------------------------- 1 | The Big Bang Theory 2 | F.R.I.E.N.D.S 3 | Game of Thrones 4 | LOST 5 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5d.csv: -------------------------------------------------------------------------------- 1 | User1, WSO2, 10000s 2 | User2, WSO2, 20000 3 | User3, WSO2, 30000 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/person.properties: -------------------------------------------------------------------------------- 1 | name=John Smith 2 | age=26 3 | occupation=Software Engineer 4 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample.csv: -------------------------------------------------------------------------------- 1 | User1, WSO2, 07xxxxxx 2 | User2, WSO2, 07xxxxxxx 3 | User3, WSO2, 07xxxxxxx -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5.csv: -------------------------------------------------------------------------------- 1 | User1, WSO2, 10000.50 2 | User2, WSO2, 20000.50 3 | User3, WSO2, 30000.00 -------------------------------------------------------------------------------- /examples/salesforce/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | distribution = "slbeta6" 3 | 4 | [build-options] 5 | observabilityIncluded = false 6 | -------------------------------------------------------------------------------- /examples/csv-processor/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | distribution = "slbeta5" 3 | 4 | [build-options] 5 | observabilityIncluded = false 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ballerina-platform/module-ballerina-io/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleWithColon.txt: -------------------------------------------------------------------------------- 1 | User1:WSO2:07xxxxxx 2 | User2:WSO2:07xxxxxxx 3 | User3:WSO2:07xxxxxxx 4 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5b.csv: -------------------------------------------------------------------------------- 1 | id, name, salary 2 | User1, WSO2, 10000 3 | User2, WSO2, 20000 4 | User3, WSO2, 30000 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5d2.csv: -------------------------------------------------------------------------------- 1 | id, name, salary 2 | User1, WSO2, 10000s 3 | User2, WSO2, 20000 4 | User3, WSO2, 30000 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample3: -------------------------------------------------------------------------------- 1 | ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 01 2c 2 | 01 2c 00 00 ff db 00 43 00 0d 09 0a 0b 0a 08 0d -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5R.csv: -------------------------------------------------------------------------------- 1 | id, name, salary 2 | User1, WSO2, 10000.50 3 | User2, WSO2, 20000.50 4 | User3, WSO2, 30000.00 -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleTdf.tsv: -------------------------------------------------------------------------------- 1 | "User1,12" WSO2 07xxxxxx 2 | User2 "WSO2,Colombo" 07xxxxxxx 3 | User3 WSO2 "07xxxxxxx,SL" -------------------------------------------------------------------------------- /examples/bow/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | distribution = "2201.0.0-20211221-194900-b414ea8e" 3 | 4 | [build-options] 5 | observabilityIncluded = false 6 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleWithHeader.csv: -------------------------------------------------------------------------------- 1 | Name Contat Email 2 | Brown,98xxxxxxx,brown@wso2.com 3 | White,98xxxxxxx,white@wso2.com 4 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample5c.csv: -------------------------------------------------------------------------------- 1 | id, name, salary, married 2 | User1, WSO2, 10000, true 3 | User2, WSO2, 20000, false 4 | User3, WSO2,, true -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleRfc.csv: -------------------------------------------------------------------------------- 1 | "User1,12",WSO2,07xxxxxx 2 | User2,"WSO2,Colombo",07xxxxxxx 3 | User3,WSO2,"07xxxxxxx,SL" 4 | User4,"",123xxxxx -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFile2.csv: -------------------------------------------------------------------------------- 1 | Distributed Computing, A001, Prof. Jack 2 | Quantum Computing, A002, Dr. Sam 3 | Artificial Intelligence, A003, Prof. Angelina 4 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample6.csv: -------------------------------------------------------------------------------- 1 | ID,Name,Age,BeverageAllowance,Total,Department 2 | 1,Person1,21,3,3.50,Eng 3 | 2,Person2,18,,,Mrk 4 | 3,Person3,35,6,7.00, -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/images/ballerina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ballerina-platform/module-ballerina-io/HEAD/native/src/test/resources/datafiles/io/images/ballerina.png -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample9.csv: -------------------------------------------------------------------------------- 1 | permanent,"one,two,three",WSO2,10000.50 2 | permanent,"four,five,six",WSO2,20000.50 3 | permanent,"seven,eight,nine",WSO2,30000.00 4 | -------------------------------------------------------------------------------- /load-tests/csv_processor/src/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | org = "wso2" 3 | name = "csv_processor" 4 | version = "0.0.1" 5 | 6 | [build-options] 7 | observabilityIncluded = false 8 | cloud = "k8s" 9 | -------------------------------------------------------------------------------- /ballerina/tests/resources/originalXmlContent.xml: -------------------------------------------------------------------------------- 1 | 2 | Tove 3 | Jani 4 | Reminder 5 | Don't forget me this weekend! 6 | 7 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "io-test-utils/" 3 | coverage: 4 | precision: 2 5 | round: down 6 | range: "60...80" 7 | status: 8 | project: 9 | default: 10 | target: 80 11 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleRef.csv: -------------------------------------------------------------------------------- 1 | id, hours_worked, name, salary, martial_status 2 | User1, 10, Jane, 10000, true 3 | User2, 20, John, 20000, false 4 | User3, 30, Jack, 30000, true -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sampleRefE.csv: -------------------------------------------------------------------------------- 1 | id, hours_worked, name, salary, martial_status 2 | User1, 10, Jane, 10000s, true 3 | User2, 20, John, 20000, false 4 | User3, 30, Jack, 30000, true -------------------------------------------------------------------------------- /compiler-plugin/src/main/resources/rules.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "kind": "VULNERABILITY", 5 | "description": "I/O function calls should not be vulnerable to path injection attacks" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /ballerina/CompilerPlugin.toml: -------------------------------------------------------------------------------- 1 | [plugin] 2 | id = "io-compiler-plugin" 3 | class = "io.ballerina.stdlib.io.compiler.IOCompilerPlugin" 4 | 5 | [[dependency]] 6 | path = "../compiler-plugin/build/libs/io-compiler-plugin-1.8.1-SNAPSHOT.jar" 7 | -------------------------------------------------------------------------------- /ballerina/tests/resources/expectedXmlCharsFile4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tove 4 | Jani 5 | Reminder 6 | Don't forget me this weekend! 7 | 8 | -------------------------------------------------------------------------------- /ballerina/tests/resources/expectedXmlCharsFile5.xml: -------------------------------------------------------------------------------- 1 | 2 | Tove 3 | Jani 4 | Reminder 5 | Don't forget me this weekend! 6 | Don't forget me this weekend! -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample8.csv: -------------------------------------------------------------------------------- 1 | permanent, 1, WSO2, 10000.50 2 | permanent, 2, WSO2, 20000.50 3 | permanent, 3, WSO2, 30000.00 4 | intern, 1, WSO2, 10000.50 5 | intern, 2, WSO2, 20000.50 6 | intern, 3, WSO2, 30000.00 7 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | ## Examples 4 | 5 | ## Checklist 6 | - [ ] Linked to an issue 7 | - [ ] Updated the changelog 8 | - [ ] Added tests 9 | - [ ] Updated the spec 10 | - [ ] Checked native-image compatibility 11 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample2.csv: -------------------------------------------------------------------------------- 1 | Xerox 1985,Dan Reichenbach,13927,-21.41,6.48,5.16,Prince Edward Island,Paper,0.37 2 | 3 | "Tennsco Lockers Sand",Guy Armstrong,15139,-1163.21,20.98,45,Prince Edward Island,Storage & Organization,0.61 -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFileWithMissingFields.csv: -------------------------------------------------------------------------------- 1 | name, designation, company, residence 2 | Anne Hamiltom, Software Engineer, Microsoft, New York 3 | John Thomson, Software Architect, WSO2, Colombo 4 | Mary Thompson, Banker, Sampath Bank, Colombo 5 | -------------------------------------------------------------------------------- /ballerina/tests/resources/expectedXmlCharsFile8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tove 4 | Jani 5 | Reminder 6 | Don't forget me this weekend! 7 | 8 | -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFile1.csv: -------------------------------------------------------------------------------- 1 | name, designation, company, age, residence 2 | Anne Hamiltom, Software Engineer, Microsoft, 26 years, New York 3 | John Thomson, Software Architect, WSO2, 38 years, Colombo 4 | Mary Thompson, Banker, Sampath Bank, 30 years, Colombo 5 | -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFileWithEmptyValues.csv: -------------------------------------------------------------------------------- 1 | name, designation, company, age, residence 2 | Anne Hamiltom, Software Engineer, Microsoft,, New York 3 | John Thomson, Software Architect, WSO2, 38 years, Colombo 4 | Mary Thompson, Banker, Sampath Bank, 30 years, 5 | -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFile1Shuffled.csv: -------------------------------------------------------------------------------- 1 | age, residence, name, designation, company 2 | 26 years, New York, Anne Hamiltom, Software Engineer, Microsoft 3 | 38 years, Colombo, John Thomson, Software Architect, WSO2 4 | 30 years, Colombo, Mary Thompson, Banker, Sampath Bank 5 | -------------------------------------------------------------------------------- /compiler-plugin-tests/src/test/resources/static_code_analyzer/ballerina_packages/rule1/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | org = "sachink" 3 | name = "rule1" 4 | version = "0.1.0" 5 | distribution = "2201.11.0-20250127-101700-a4b67fe5" 6 | 7 | [build-options] 8 | observabilityIncluded = true 9 | -------------------------------------------------------------------------------- /load-tests/csv_processor/deployment/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - csv_processor.yaml 3 | - ingress.yaml 4 | patches: 5 | - path: deployment-patch.yaml 6 | target: 7 | group: apps 8 | version: v1 9 | kind: Deployment 10 | name: io-csv-processor-deployment 11 | -------------------------------------------------------------------------------- /ballerina/tests/resources/expectedXmlCharsFile7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tove 4 | Jani 5 | Reminder 6 | Don't forget me this weekend! 7 | 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # See: https://help.github.com/articles/about-codeowners/ 5 | 6 | # These owners will be the default owners for everything in the repo. 7 | * @NipunaRanasinghe @ayeshLK @shafreenAnfar 8 | -------------------------------------------------------------------------------- /load-tests/csv_processor/deployment/deployment-patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "apps/v1" 2 | kind: Deployment 3 | metadata: 4 | name: no-name 5 | spec: 6 | template: 7 | metadata: 8 | labels: 9 | logs: "true" 10 | spec: 11 | containers: 12 | - name: "io-csv-processor-deployment" 13 | imagePullPolicy: Always 14 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample4.csv: -------------------------------------------------------------------------------- 1 | Xerox 1985,Dan Reichenbach,13927,-21.41,6.48,5.16,Prince Edward Island,Paper,0.37,Xerox 1985,Dan Reichenbach,13927,-21.41,6.48,5.16,Prince Edward Island,Paper,0.37 2 | Xerox 19,Dan Reichenbach,13927,-21.41,6.48,5.16,Prince Edward Island,Paper,0.37,Xerox 1985,Dan Reichenbach,13927,-21.41,6.48,5.16,Prince Edward Island,Paper,0.37 -------------------------------------------------------------------------------- /ballerina/tests/resources/csvResourceFile1WithMulltipleHeaders.csv: -------------------------------------------------------------------------------- 1 | name, designation, company, age, residence 2 | name, designation, company, age, residence 3 | name, designation, company, age, residence 4 | Anne Hamiltom, Software Engineer, Microsoft, 26 years, New York 5 | John Thomson, Software Architect, WSO2, 38 years, Colombo 6 | Mary Thompson, Banker, Sampath Bank, 30 years, Colombo 7 | -------------------------------------------------------------------------------- /.github/workflows/trivy-scan.yml: -------------------------------------------------------------------------------- 1 | name: Trivy 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "30 20 * * *" 7 | 8 | jobs: 9 | call_workflow: 10 | name: Run Trivy Scan Workflow 11 | if: ${{ github.repository_owner == 'ballerina-platform' }} 12 | uses: ballerina-platform/ballerina-library/.github/workflows/trivy-scan-template.yml@main 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /load-tests/csv_processor/src/Cloud.toml: -------------------------------------------------------------------------------- 1 | [container.image] 2 | repository= "ballerina" 3 | name="csv_processor" 4 | 5 | [cloud.deployment] 6 | min_memory="256Mi" 7 | max_memory="512Mi" 8 | min_cpu="200m" 9 | max_cpu="1000m" 10 | 11 | [cloud.deployment.autoscaling] 12 | min_replicas=1 13 | max_replicas=1 14 | 15 | [[container.copy.files]] 16 | sourceFile="./resources/ghz_output.csv" 17 | target="/home/ballerina/resources/ghz_output.csv" 18 | -------------------------------------------------------------------------------- /ballerina/tests/resources/expectedXmlCharsFile6.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | ]> 8 | 9 | Tove 10 | Jani 11 | Reminder 12 | Don't forget me this weekend! 13 | 14 | -------------------------------------------------------------------------------- /load-tests/csv_processor/deployment/ingress.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | name: io-csv-processor 6 | annotations: 7 | kubernetes.io/ingress.class: nginx 8 | spec: 9 | rules: 10 | - host: bal.perf.test 11 | http: 12 | paths: 13 | - path: "/" 14 | pathType: Prefix 15 | backend: 16 | service: 17 | name: csv-processor-s 18 | port: 19 | number: 9090 20 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: PR Build 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} 5 | cancel-in-progress: true 6 | 7 | on: [pull_request] 8 | 9 | jobs: 10 | call_workflow: 11 | name: Run PR Build Workflow 12 | if: ${{ github.repository_owner == 'ballerina-platform' }} 13 | uses: ballerina-platform/ballerina-library/.github/workflows/pull-request-build-template.yml@main 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.caching=true 2 | group=io.ballerina.stdlib 3 | version=1.8.1-SNAPSHOT 4 | ballerinaLangVersion=2201.12.0 5 | testngVersion=7.6.1 6 | slf4jVersion=1.7.30 7 | jacocoVersion=0.8.10 8 | spotbugsPluginVersion=6.0.18 9 | shadowJarPluginVersion=8.1.1 10 | downloadPluginVersion=5.4.0 11 | releasePluginVersion=2.8.0 12 | checkstyleToolVersion=10.12.0 13 | ballerinaGradlePluginVersion=2.3.0 14 | gsonVersion=2.7 15 | checkstylePluginVersion=10.12.0 16 | balScanVersion=0.10.0 17 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release 2 | 3 | on: 4 | workflow_dispatch: 5 | repository_dispatch: 6 | types: [stdlib-release-pipeline] 7 | 8 | jobs: 9 | call_workflow: 10 | name: Run Release Workflow 11 | if: ${{ github.repository_owner == 'ballerina-platform' }} 12 | uses: ballerina-platform/ballerina-library/.github/workflows/release-package-template.yml@main 13 | secrets: inherit 14 | with: 15 | package-name: io 16 | package-org: ballerina 17 | -------------------------------------------------------------------------------- /.github/workflows/build-timestamped-master.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - "*.md" 9 | - "docs/**" 10 | - "load-tests/**" 11 | workflow_dispatch: 12 | 13 | jobs: 14 | call_workflow: 15 | name: Run Build Workflow 16 | if: ${{ github.repository_owner == 'ballerina-platform' }} 17 | uses: ballerina-platform/ballerina-library/.github/workflows/build-timestamp-master-template.yml@main 18 | secrets: inherit 19 | -------------------------------------------------------------------------------- /.github/workflows/fossa_scan.yml: -------------------------------------------------------------------------------- 1 | name: Fossa Scan 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '30 18 * * *' # 00:00 in LK time (GMT+5:30) 6 | jobs: 7 | fossa-scan: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: fossas/fossa-action@main 12 | env: 13 | packageUser: ${{ secrets.BALLERINA_BOT_USERNAME }} 14 | packagePAT: ${{ secrets.BALLERINA_BOT_TOKEN }} 15 | with: 16 | api-key: ${{secrets.FOSSA_APIKEY}} 17 | -------------------------------------------------------------------------------- /examples/salesforce/resources/data.csv: -------------------------------------------------------------------------------- 1 | Description,FirstName,LastName,Title,Phone,Email 2 | Created_from_Ballerina_Sf_Bulk_API,John,Hooch,Professor Level 01,344-776-67577,john.hooch@wsj.com 3 | Created_from_Ballerina_Sf_Bulk_API,Ann,Green,HR Admin,344-776-67574,ann.green@wsj.com 4 | Created_from_Ballerina_Sf_Bulk_API,Nichole,Santner,Software Engineer,344-756-67577,nichole.santner@wsj.com 5 | Created_from_Ballerina_Sf_Bulk_API,Kamala,Patel,AI Engineer,344-756-673457,kamala.patel@wsj.com 6 | Created_from_Ballerina_Sf_Bulk_API,Raj,Alexander,ML Engineer,344-756-673457,raj.alex@wsj.com 7 | -------------------------------------------------------------------------------- /.github/workflows/process-load-test-result.yml: -------------------------------------------------------------------------------- 1 | name: Process load test results 2 | on: 3 | repository_dispatch: 4 | types: [io-load-test] 5 | 6 | jobs: 7 | call_stdlib_process_load_test_results_workflow: 8 | name: Run StdLib Process Load Test Results Workflow 9 | uses: ballerina-platform/ballerina-library/.github/workflows/process-load-test-results-template.yml@main 10 | with: 11 | results: ${{ toJson(github.event.client_payload.results) }} 12 | secrets: 13 | ballerina_bot_token: ${{ secrets.BALLERINA_BOT_TOKEN }} 14 | ballerina_reviewer_bot_token: ${{ secrets.BALLERINA_REVIEWER_BOT_TOKEN }} 15 | -------------------------------------------------------------------------------- /.github/workflows/central-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to the Ballerina central 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | environment: 7 | type: choice 8 | description: Select Environment 9 | required: true 10 | options: 11 | - DEV CENTRAL 12 | - STAGE CENTRAL 13 | 14 | jobs: 15 | call_workflow: 16 | name: Run Central Publish Workflow 17 | if: ${{ github.repository_owner == 'ballerina-platform' }} 18 | uses: ballerina-platform/ballerina-library/.github/workflows/central-publish-template.yml@main 19 | secrets: inherit 20 | with: 21 | environment: ${{ github.event.inputs.environment }} 22 | -------------------------------------------------------------------------------- /compiler-plugin-tests/src/test/resources/static_code_analyzer/expected_output/rule1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "location": { 4 | "filePath": "main.bal", 5 | "startLine": 23, 6 | "endLine": 23, 7 | "startColumn": 31, 8 | "endColumn": 58, 9 | "startOffset": 894, 10 | "length": 27 11 | }, 12 | "rule": { 13 | "id": "ballerina/io:1", 14 | "numericId": 1, 15 | "description": "I/O function calls should not be vulnerable to path injection attacks", 16 | "ruleKind": "VULNERABILITY" 17 | }, 18 | "source": "BUILT_IN", 19 | "fileName": "rule1/main.bal", 20 | "filePath": "**PATH_TO_MODULE_ROOT**/module-ballerina-io/compiler-plugin-tests/src/test/resources/static_code_analyzer/ballerina_packages/rule1/main.bal" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | build 26 | .gradle/ 27 | target 28 | 29 | # IDEA Files 30 | .idea/ 31 | *.iml 32 | *.ipr 33 | *.iws 34 | 35 | # VSCode files 36 | .project 37 | .classpath 38 | .settings 39 | bin/ 40 | 41 | # MacOS 42 | *.DS_Store 43 | 44 | # Ballerina 45 | velocity.log* 46 | *Ballerina.lock 47 | examples/**/Dependencies.toml 48 | load-tests/**/Dependencies.toml 49 | ballerina/Dependencies 2.toml 50 | 51 | compiler-plugin-tests/**/target 52 | -------------------------------------------------------------------------------- /spotbugs-exclude.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ballerina/tests/test_constants.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | const string RESOURCES_BASE_PATH = "../native/src/test/resources/"; 18 | const string TEMP_DIR = "build/tmpdir/"; 19 | const string TEST_RESOURCE_PATH = "tests/resources/"; 20 | -------------------------------------------------------------------------------- /ballerina/init.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/jballerina.java; 18 | 19 | function init() { 20 | setModule(); 21 | } 22 | 23 | function setModule() = @java:Method { 24 | 'class: "io.ballerina.stdlib.io.nativeimpl.ModuleUtils" 25 | } external; 26 | -------------------------------------------------------------------------------- /ballerina/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | org = "ballerina" 3 | name = "io" 4 | version = "1.8.1" 5 | authors = ["Ballerina"] 6 | keywords = ["io", "json", "xml", "csv", "file"] 7 | repository = "https://github.com/ballerina-platform/module-ballerina-io" 8 | icon = "icon.png" 9 | license = ["Apache-2.0"] 10 | distribution = "2201.12.0" 11 | 12 | [platform.java21] 13 | graalvmCompatible = true 14 | 15 | [[platform.java21.dependency]] 16 | groupId = "io.ballerina.stdlib" 17 | artifactId = "io-native" 18 | path = "../native/build/libs/io-native-1.8.1-SNAPSHOT.jar" 19 | version = "1.8.1" 20 | 21 | [[platform.java21.dependency]] 22 | groupId = "io.ballerina.stdlib" 23 | artifactId = "io-compiler-plugin" 24 | version = "1.8.1" 25 | path = "../compiler-plugin/build/libs/io-compiler-plugin-1.8.1-SNAPSHOT.jar" 26 | 27 | [[platform.java21.dependency]] 28 | path = "../test-utils/build/libs/io-test-utils-1.8.1-SNAPSHOT.jar" 29 | scope = "testOnly" 30 | version = "1.8.1-SNAPSHOT" 31 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | module io.ballerina.stdlib.io.compiler { 20 | requires io.ballerina.lang; 21 | requires io.ballerina.tools.api; 22 | requires io.ballerina.parser; 23 | requires io.ballerina.scan; 24 | } 25 | -------------------------------------------------------------------------------- /test-utils/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | module io.ballerina.stdlib.io.testutils { 20 | requires io.ballerina.runtime; 21 | requires io.ballerina.stdlib.io; 22 | exports io.ballerina.stdlib.io.testutils; 23 | } 24 | -------------------------------------------------------------------------------- /ballerina/channel.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | type ReadableChannel ReadableByteChannel|ReadableCharacterChannel|ReadableTextRecordChannel|ReadableCSVChannel; 18 | 19 | type WritableChannel WritableByteChannel|WritableCharacterChannel|WritableTextRecordChannel|WritableCSVChannel; 20 | -------------------------------------------------------------------------------- /compiler-plugin-tests/src/test/resources/static_code_analyzer/ballerina_packages/rule1/main.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 WSO2 LLC. (http://www.wso2.org) 2 | // 3 | // WSO2 LLC. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/io; 18 | import ballerina/http; 19 | 20 | service /fileService on new http:Listener(8080) { 21 | resource function get file(string fileName) returns string|error { 22 | string filePath = "./resources/" + fileName; 23 | 24 | string content = check io:fileReadString(filePath); 25 | return content; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /load-tests/csv_processor/scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # Copyright 2021 WSO2 Inc. (http://wso2.org) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # ---------------------------------------------------------------------------- 17 | # Execusion script for ballerina performance tests 18 | # ---------------------------------------------------------------------------- 19 | set -e 20 | source base-scenario.sh 21 | 22 | jmeter -n -t "$scriptsDir/"http-get-request.jmx -l "$resultsDir/"original.jtl -Jusers=2 -Jduration=3600 -Jhost=bal.perf.test -Jport=80 -Jprotocol=http -Jpath=BalPerformance/grpc $payload_flags 23 | -------------------------------------------------------------------------------- /native/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | module io.ballerina.stdlib.io { 20 | requires io.ballerina.runtime; 21 | requires org.slf4j; 22 | exports io.ballerina.stdlib.io.channels; 23 | exports io.ballerina.stdlib.io.channels.base; 24 | exports io.ballerina.stdlib.io.channels.base.data; 25 | exports io.ballerina.stdlib.io.csv; 26 | exports io.ballerina.stdlib.io.nativeimpl; 27 | exports io.ballerina.stdlib.io.readers; 28 | exports io.ballerina.stdlib.io.utils; 29 | } 30 | -------------------------------------------------------------------------------- /compiler-plugin-tests/src/test/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.github/workflows/trigger-load-tests.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Load Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | tests: 7 | description: > 8 | List of test names. This needs to be filled only if you want to run a specific set of tests. Example: foo,bar 9 | required: false 10 | clusterName: 11 | description: 'Cluster name' 12 | default: 'io-perf-cluster-test' 13 | required: false 14 | schedule: 15 | - cron: '30 0 * * *' 16 | 17 | jobs: 18 | call_stdlib_trigger_load_test_workflow: 19 | name: Run StdLib Load Test Workflow 20 | if: ${{ github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository_owner == 'ballerina-platform') }} 21 | uses: ballerina-platform/ballerina-library/.github/workflows/trigger-load-tests-template.yml@main 22 | with: 23 | repo_name: 'module-ballerina-io' 24 | runtime_artifacts_url: 'https://api.github.com/repos/ballerina-platform/module-ballerina-io/actions/artifacts' 25 | dispatch_type: 'io-load-test' 26 | cluster_name: ${{ inputs.clusterName }} 27 | tests: ${{ inputs.tests }} 28 | branch: ${{ inputs.branch }} 29 | secrets: 30 | ballerina_bot_token: ${{ secrets.BALLERINA_BOT_TOKEN }} 31 | -------------------------------------------------------------------------------- /test-utils/src/main/java/io/ballerina/stdlib/io/testutils/EnvironmentTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.testutils; 20 | 21 | import java.util.Locale; 22 | 23 | /** 24 | * This class holds test utility APIs related to check the running OS. 25 | * 26 | */ 27 | public class EnvironmentTestUtils { 28 | 29 | private EnvironmentTestUtils() { 30 | } 31 | 32 | public static boolean isWindowsEnvironment() { 33 | return System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/staticcodeanalyzer/RuleFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler.staticcodeanalyzer; 20 | 21 | import io.ballerina.scan.Rule; 22 | import io.ballerina.scan.RuleKind; 23 | 24 | /** 25 | * {@code RuleFactory} contains the logic to create a {@link Rule}. 26 | */ 27 | public class RuleFactory { 28 | 29 | private RuleFactory() {} 30 | 31 | public static Rule createRule(int id, String description, RuleKind kind) { 32 | return new RuleImpl(id, description, kind); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/utils/BallerinaIOException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.utils; 20 | 21 | /** 22 | * Will be used to throw Ballerina I/O related runtime exceptions. 23 | */ 24 | public class BallerinaIOException extends Exception { 25 | 26 | private static final long serialVersionUID = 816072850401725144L; 27 | 28 | public BallerinaIOException(String message, Throwable cause) { 29 | super(message, cause); 30 | } 31 | 32 | public BallerinaIOException(String message) { 33 | super(message); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ballerina/read.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/jballerina.java; 18 | 19 | # Reads a line of input from the standard input (STDIN). 20 | # If an argument is provided, it will be printed as a prompt before reading the input. 21 | # ```ballerina 22 | # string choice = io:readln("Enter choice 1 - 5: "); 23 | # string choice = io:readln(); 24 | # ``` 25 | # 26 | # + a - An optional value to be printed before reading the input 27 | # + return - Input read from the STDIN 28 | public function readln(any? a = ()) returns string = @java:Method { 29 | name: "readln", 30 | 'class: "io.ballerina.stdlib.io.nativeimpl.ReadlnAny" 31 | } external; 32 | -------------------------------------------------------------------------------- /native/src/test/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/bow/A Guideline on Implementing Bag of Word Model Generator.md: -------------------------------------------------------------------------------- 1 | # Bag of Word Model Generator 2 | 3 | ## Overview 4 | 5 | Bag-of-Word (BoW) is a mechanism used in Natural Language Processing (NLP) to extract features in documents and texts. This example implements a simple BoW model using Ballerina I/O operations. 6 | 7 | ## Implementation 8 | 9 | The input for this program is a raw text file. The program reads the given raw-text file line by line as a stream using the following I/O API. 10 | 11 | ```ballerina 12 | stream lineStream = check io:fileReadLinesAsStream("./resources/data.txt"); 13 | ``` 14 | 15 | Then process each line in the stream to generate the BoW model. 16 | 17 | ## Run the Example 18 | 19 | First, clone this repository, and then run the following commands to run the example on your local machine. 20 | 21 | ```sh 22 | $ cd examples/bow 23 | $ bal run 24 | ``` 25 | 26 | Then provide the input value. This input value indicates the number of most frequent words users wants to retrieve. For example: 27 | 28 | ``` 29 | > Enter the number of most frequent words to retrieve: 10 30 | ``` 31 | 32 | Here, the boundary value 10 means it gives the most frequent ten words along with their frequencies as a map. 33 | 34 | ```sh 35 | Most frequent 10 words are: 36 | {"ballerina":100,"grpc":59,"is":41,"the":176,"to":50,"and":49,"client":41,"service":53,"a":51,"rpc":52} 37 | ``` 38 | -------------------------------------------------------------------------------- /ballerina/tests/open_io.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/test; 17 | import ballerina/lang.'string as langstring; 18 | 19 | @test:Config {} 20 | isolated function testOpenReadableFileWithMissingFile() { 21 | ReadableByteChannel|Error err = openReadableFile("xxx.txt"); 22 | test:assertTrue(err is Error); 23 | test:assertTrue(langstring:includes((err).message(), "no such file or directory:")); 24 | } 25 | 26 | @test:Config {} 27 | isolated function testOpenReadableCsvFileWithMissingFile() { 28 | ReadableCSVChannel|Error err = openReadableCsvFile("xxx.csv"); 29 | test:assertTrue(err is Error); 30 | test:assertTrue(langstring:includes((err).message(), "no such file or directory:")); 31 | } 32 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/records/sample7.csv: -------------------------------------------------------------------------------- 1 | Common App ID,Application Created Date,Prospect Export Date,First name,Middle name,Last name,Sex,birth,Address1,Address2,City,State,Zip,Country,address,number,Latino,status,CeebCode111111111122222222223333333333444445444445555555555666666666677777777778888888888999999999900000000001111111111222222222233333333334444444444555555555566666666667777777777888888889999999900000000000000000000111111111122222222223333333333444444444455555555556666666666777777777788888888999999990000000000 2 | 11111111,08052018,1,Frank,N,Hussle,M,09232001,2525 Conway Ct,Apt A,Fremont,CA,94539-6715,USA,someonesemailaddress@yahoo.com,15101112222,N,Citizen,050911 3 | 22222222,08052018,1,Rihanna,O,Shanks,F,11102000,800 Hillcrest Dr,Apt D,Shaker Heights,IL,11111-1111,USA,someemail2@gmail.com,18471111212,N,Citizen,111111 4 | 33333333,08052018,1,Shanna,Faith,Arnold,F,08302001,3737 Josh Centre Blvd,Apt C,MISSISSAUGA,ON,L5M 6Z9,CAN,someonesemailaddress@yahoo.com,1647334444,N,Citizen,826322 5 | 44444444,08062018,1,Mark,P,McBride,M,02182000,89 Nickel Ln,Apt E,Columbus,OH,43230-2285,USA,someonesemailaddress@yahoo.com,12154445555,N,Citizen,111133 6 | 55555555,08072018,1,Curt,Michael,Burns,M,08251994,3545D Maryway Knoll Ln,Apt A,Columbus,OH,43215-6245,USA,kevin.m.someonesemailaddress@yahoo.com,13046667777,N,Citizen,490644 7 | 55555556,07302018,1,Brenda,M,Dutch,F,10212002,311 Bronco St,Unit 111,Gaithersburg,MD,20878-6111,USA,someemail@gmail.com,13019111222,N,Citizen,110114 -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/base/data/LongResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | * 18 | */ 19 | 20 | package io.ballerina.stdlib.io.channels.base.data; 21 | 22 | /** 23 | * Represents a long read though the data channel. 24 | */ 25 | public class LongResult { 26 | /** 27 | * Value of the long which is read. 28 | */ 29 | private long value; 30 | /** 31 | * Number of bytes read. 32 | */ 33 | private int byteCount; 34 | 35 | public LongResult(long value, int byteCount) { 36 | this.value = value; 37 | this.byteCount = byteCount; 38 | } 39 | 40 | public long getValue() { 41 | return value; 42 | } 43 | 44 | public int getByteCount() { 45 | return byteCount; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/nativeimpl/ModuleUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.nativeimpl; 20 | 21 | import io.ballerina.runtime.api.Environment; 22 | import io.ballerina.runtime.api.Module; 23 | 24 | /** 25 | * This class will hold module related utility functions. 26 | * 27 | * @since 2.0.0 28 | */ 29 | public class ModuleUtils { 30 | 31 | /** 32 | * I/O standard library package ID. 33 | */ 34 | private static Module ioModule = null; 35 | 36 | private ModuleUtils() { 37 | } 38 | 39 | public static void setModule(Environment env) { 40 | ioModule = env.getCurrentModule(); 41 | } 42 | 43 | public static Module getModule() { 44 | return ioModule; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/bytes/ReadByteResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.bytes; 20 | 21 | /** 22 | * Read byte result. 23 | */ 24 | public class ReadByteResult { 25 | /** 26 | * Holds the read byte content. 27 | */ 28 | private byte [] content; 29 | /** 30 | * Number of bytes read. 31 | */ 32 | private int numberOfBytesRead; 33 | 34 | public ReadByteResult(byte[] content, int numberOfBytesRead) { 35 | this.content = content; 36 | this.numberOfBytesRead = numberOfBytesRead; 37 | } 38 | 39 | public byte[] getContent() { 40 | return content; 41 | } 42 | 43 | public int getNumberOfBytesRead() { 44 | return numberOfBytesRead; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/build-with-bal-test-graalvm.yml: -------------------------------------------------------------------------------- 1 | name: GraalVM Check 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | lang_tag: 7 | description: Branch/Release Tag of the Ballerina Lang 8 | required: true 9 | default: master 10 | lang_version: 11 | description: Ballerina Lang Version (If given ballerina lang buid will be skipped) 12 | required: false 13 | default: '' 14 | native_image_options: 15 | description: Default native-image options 16 | required: false 17 | default: '' 18 | schedule: 19 | - cron: '30 18 * * *' 20 | pull_request: 21 | branches: 22 | - master 23 | types: [ opened, synchronize, reopened, labeled, unlabeled ] 24 | 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | call_stdlib_workflow: 31 | name: Run StdLib Workflow 32 | if: ${{ github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository_owner == 'ballerina-platform') }} 33 | uses: ballerina-platform/ballerina-library/.github/workflows/build-with-bal-test-graalvm-template.yml@main 34 | with: 35 | lang_tag: ${{ inputs.lang_tag }} 36 | lang_version: ${{ inputs.lang_version }} 37 | native_image_options: ${{ inputs.native_image_options }} 38 | additional_ubuntu_build_flags: '-x :io-native:test' 39 | additional_windows_build_flags: '-x :io-native:test' 40 | -------------------------------------------------------------------------------- /examples/csv-processor/A Guildeline on Processing CSV Files.md: -------------------------------------------------------------------------------- 1 | # CSV Processor 2 | 3 | ## Overview 4 | 5 | CSV processor is an example that demonstrates the usage of CSV stream in the Ballerina I/O package. 6 | 7 | ## Implementation 8 | 9 | This sample implementation reads a large CSV file (with nearly 0.2 million) records and provides summarized results. The dataset is as follows. 10 | 11 | ```csv 12 | duration (ms),status,error 13 | 228.92,OK, 14 | 227.24,OK, 15 | 229.47,OK, 16 | ``` 17 | 18 | The columns of the dataset are as follows. 19 | 1. The first column contains the response time of each request in milliseconds 20 | 2. The second column has the response status (e.g., OK, PermissionDenied, or Unavailable etc.) 21 | 3. Third column state, if there is an error, the relevant error message 22 | 23 | This example uses the output result of Ballerina gRPC performance tests and returns the average running time, number of successful cases, and number of failure cases as the output. The first task of the example is to read the given CSV file as a stream. 24 | 25 | ```ballerina 26 | stream performanceDataStream = check io:fileReadCsvAsStream("resources/grpc_performance_output.csv"); 27 | ``` 28 | 29 | Then, it iterates through the result stream to read each entry and return the summarized performance results. 30 | 31 | ## Run the Example 32 | 33 | First, clone this repository, and then run the following commands to run the example on your local machine. 34 | 35 | ```sh 36 | $ cd examples/csv-processor 37 | $ bal run 38 | ``` 39 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/staticcodeanalyzer/IOCodeAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler.staticcodeanalyzer; 20 | 21 | import io.ballerina.compiler.syntax.tree.SyntaxKind; 22 | import io.ballerina.projects.plugins.CodeAnalysisContext; 23 | import io.ballerina.projects.plugins.CodeAnalyzer; 24 | import io.ballerina.scan.Reporter; 25 | 26 | /** 27 | * File code analyser. 28 | */ 29 | public class IOCodeAnalyzer extends CodeAnalyzer { 30 | private final Reporter reporter; 31 | 32 | public IOCodeAnalyzer(Reporter reporter) { 33 | this.reporter = reporter; 34 | } 35 | 36 | @Override 37 | public void init(CodeAnalysisContext codeAnalysisContext) { 38 | codeAnalysisContext.addSyntaxNodeAnalysisTask(new IOPathInjectionAnalyzer(reporter), SyntaxKind.FUNCTION_CALL); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/IOCompilerPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler; 20 | 21 | import io.ballerina.projects.plugins.CompilerPlugin; 22 | import io.ballerina.projects.plugins.CompilerPluginContext; 23 | import io.ballerina.scan.ScannerContext; 24 | import io.ballerina.stdlib.io.compiler.staticcodeanalyzer.IOCodeAnalyzer; 25 | 26 | import static io.ballerina.stdlib.io.compiler.Constants.SCANNER_CONTEXT; 27 | 28 | /** 29 | * File compiler plugin. 30 | */ 31 | public class IOCompilerPlugin extends CompilerPlugin { 32 | 33 | @Override 34 | public void init(CompilerPluginContext context) { 35 | Object object = context.userData().get(SCANNER_CONTEXT); 36 | if (object instanceof ScannerContext scannerContext) { 37 | context.addCodeAnalyzer(new IOCodeAnalyzer(scannerContext.getReporter())); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test-utils/src/main/java/io/ballerina/stdlib/io/testutils/FileTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.testutils; 19 | 20 | import io.ballerina.runtime.api.values.BString; 21 | 22 | import java.io.IOException; 23 | import java.nio.file.Files; 24 | import java.nio.file.Path; 25 | import java.nio.file.Paths; 26 | 27 | /** 28 | * This class holds test utility APIs related to file API test cases. 29 | * 30 | */ 31 | public class FileTestUtils { 32 | 33 | private FileTestUtils() { 34 | } 35 | 36 | public static void createDirectory(BString path) { 37 | Path directoryPath = Paths.get(path.getValue()); 38 | if (!Files.exists(directoryPath)) { 39 | try { 40 | Files.createDirectory(directoryPath); 41 | } catch (IOException e) { 42 | //Removed logs from here 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/update_specs.yml: -------------------------------------------------------------------------------- 1 | name: Update Specifications 2 | 3 | env: 4 | SPEC_FOLDER_PATH: 'docs/spec' 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | branches: 10 | - master 11 | paths: 12 | - 'docs/spec/**' 13 | 14 | jobs: 15 | update_specs: 16 | name: Update Specifications 17 | if: github.repository_owner == 'ballerina-platform' 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Checkout Repository 22 | uses: actions/checkout@v2 23 | 24 | - name: Get current date 25 | id: date 26 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 27 | 28 | - name: Get Repo Name 29 | id: repo_name 30 | run: | 31 | MODULE=${{ github.event.repository.name }} 32 | echo "::set-output name=short_name::${MODULE##*-}" 33 | 34 | - name: Trigger Workflow 35 | run: | 36 | curl --request POST \ 37 | 'https://api.github.com/repos/ballerina-platform/ballerina-dev-website/dispatches' \ 38 | -H 'Accept: application/vnd.github.v3+json' \ 39 | -H 'Authorization: Bearer ${{ secrets.BALLERINA_BOT_TOKEN }}' \ 40 | --data "{ 41 | \"event_type\": \"update-stdlib-specs\", 42 | \"client_payload\": { 43 | \"module_name\": \"${{ github.event.repository.name }}\", 44 | \"short_name\": \"${{ steps.repo_name.outputs.short_name }}\", 45 | \"file_dir\": \"${{ github.event.repository.name }}/${{ env.SPEC_FOLDER_PATH }}\", 46 | \"release_date\": \"${{ steps.date.outputs.date }}\" 47 | } 48 | }" 49 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/MockByteChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | * 18 | */ 19 | 20 | package io.ballerina.stdlib.io; 21 | 22 | import io.ballerina.stdlib.io.channels.base.Channel; 23 | 24 | import java.nio.channels.ByteChannel; 25 | import java.nio.channels.WritableByteChannel; 26 | 27 | /** 28 | * Mock implementation of byte channel for testing purposes. 29 | */ 30 | public class MockByteChannel extends Channel { 31 | 32 | public MockByteChannel(ByteChannel channel) { 33 | super(channel); 34 | } 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | public void transfer(int position, int count, WritableByteChannel dstChannel) { 41 | throw new UnsupportedOperationException(); 42 | } 43 | 44 | @Override 45 | public Channel getChannel() { 46 | throw new UnsupportedOperationException(); 47 | } 48 | 49 | public boolean remaining() { 50 | return false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/utils/Base64Wrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.utils; 20 | 21 | import io.ballerina.stdlib.io.channels.base.Channel; 22 | 23 | import java.nio.channels.WritableByteChannel; 24 | 25 | /** 26 | * Wrap base64 byte channel stream as a ballerina specific byte channel. 27 | * 28 | * @since 0.970.0 29 | */ 30 | public class Base64Wrapper extends Channel { 31 | public Base64Wrapper(Base64ByteChannel channel) { 32 | super(channel); 33 | } 34 | 35 | @Override 36 | public void transfer(int position, int count, WritableByteChannel dstChannel) { 37 | //For the time being not applicable 38 | throw new UnsupportedOperationException(); 39 | } 40 | 41 | @Override 42 | public Channel getChannel() { 43 | throw new UnsupportedOperationException(); 44 | } 45 | 46 | @Override 47 | public boolean remaining() { 48 | return false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/BlobIOChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.channels.base.Channel; 21 | 22 | import java.nio.channels.WritableByteChannel; 23 | 24 | /** 25 | * Creates a blob channel to perform I/O operations. 26 | */ 27 | public class BlobIOChannel extends Channel { 28 | 29 | public BlobIOChannel(BlobChannel channel) { 30 | super(channel); 31 | this.setReadable(channel.isReadable()); 32 | } 33 | 34 | /** 35 | * {@inheritDoc} 36 | */ 37 | @Override 38 | public void transfer(int position, int count, WritableByteChannel dstChannel) { 39 | throw new UnsupportedOperationException(); 40 | } 41 | 42 | @Override 43 | public Channel getChannel() { 44 | throw new UnsupportedOperationException(); 45 | } 46 | 47 | @Override 48 | public boolean remaining() { 49 | return false; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /examples/salesforce/A Guildeline on Salesforce Bulk Processing.md: -------------------------------------------------------------------------------- 1 | # Salesforce Bulk Processing 2 | 3 | ## Overview 4 | 5 | This example demonstrates the usage of I/O CSV streaming APIs directly with the Ballerina Salesforce connector APIs. 6 | 7 | ## Implementation 8 | 9 | To run this example, you have to first create a Salesforce account and get an authentication token to connect to it. For more information about creating a Salesforce authentication token, refer to [this documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/quickstart_oauth.htm). 10 | 11 | Before running the example, you have to set the following Ballerina configurable variables in the `Config.toml` file. 12 | ```toml 13 | BASE_URL="" 14 | SF_TOKEN="" 15 | ``` 16 | 17 | This example first reads the given CSV contact details using I/O streaming APIs as follows. 18 | 19 | ```ballerina 20 | stream csvStream = check io:fileReadCsvAsStream(csvContactsFilePath); 21 | ``` 22 | 23 | Then, pass these contact details stream to the Salesforce bulk API to create a new set of contacts in Salesforce. 24 | 25 | ```ballerina 26 | sbulk:BulkJob queryJob = check baseClient->createJob("insert", "Contact", "CSV"); 27 | sbulk:BatchInfo batch = check baseClient->addBatch(queryJob, csvStream); 28 | ``` 29 | 30 | Refer to [this documentation](https://central.ballerina.io/ballerinax/salesforce) to learn more about the Ballerina Salesforce APIs. 31 | 32 | 33 | ## Run the Example 34 | 35 | First, clone this repository, and then run the following commands to run the example on your local machine. 36 | 37 | ```sh 38 | $ cd examples/salesforce 39 | $ bal run 40 | ``` 41 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/staticcodeanalyzer/RuleImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler.staticcodeanalyzer; 20 | 21 | import io.ballerina.scan.Rule; 22 | import io.ballerina.scan.RuleKind; 23 | 24 | public class RuleImpl implements Rule { 25 | private final int id; 26 | private final String description; 27 | private final RuleKind kind; 28 | 29 | RuleImpl(int id, String description, RuleKind kind) { 30 | this.id = id; 31 | this.description = description; 32 | this.kind = kind; 33 | } 34 | 35 | @Override 36 | public String id() { 37 | return Integer.toString(this.id); 38 | } 39 | 40 | @Override 41 | public int numericId() { 42 | return this.id; 43 | } 44 | 45 | @Override 46 | public String description() { 47 | return this.description; 48 | } 49 | 50 | @Override 51 | public RuleKind kind() { 52 | return this.kind; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ballerina/io_error.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Represents IO module related errors. 18 | public type Error distinct error; 19 | 20 | # This will return when connection timed out happen when try to connect to a remote host. 21 | public type ConnectionTimedOutError distinct Error; 22 | 23 | # Represents generic IO error. The detail record contains the information related to the error. 24 | public type GenericError distinct Error; 25 | 26 | # This will get returned due to file permission issues. 27 | public type AccessDeniedError distinct Error; 28 | 29 | # This will get returned if the file is not available in the given file path. 30 | public type FileNotFoundError distinct Error; 31 | 32 | # This will get returned when there is an mismatch of given type and the expected type. 33 | public type TypeMismatchError distinct Error; 34 | 35 | # This will get returned if read operations are performed on a channel after it closed. 36 | public type EofError distinct Error; 37 | 38 | # This will get returned if there is an invalid configuration. 39 | public type ConfigurationError distinct Error; 40 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler; 20 | 21 | import java.util.List; 22 | 23 | public class Constants { 24 | private Constants() {} 25 | 26 | public static final String SCANNER_CONTEXT = "ScannerContext"; 27 | public static final String IO = "io"; 28 | public static final String BALLERINA_ORG = "ballerina"; 29 | 30 | public static final List IO_FUNCTIONS = List.of( 31 | "fileReadBytes", 32 | "fileWriteBytes", 33 | "fileReadBlocksAsStream", 34 | "fileWriteBlocksFromStream", 35 | "fileWriteString", 36 | "fileReadString", 37 | "fileWriteLines", 38 | "fileReadLines", 39 | "fileWriteLinesFromStream", 40 | "fileWriteCsv", 41 | "fileReadCsv", 42 | "fileWriteCsvFromStream", 43 | "fileReadCsvAsStream", 44 | "fileWriteJson", 45 | "fileReadJson", 46 | "fileWriteXml", 47 | "fileReadXml" 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /native/src/test/resources/datafiles/io/text/longParagraph.txt: -------------------------------------------------------------------------------- 1 | Ballerina is a general purpose, concurrent and strongly typed programming language with both textual and graphical 2 | syntaxes, optimized for integration. 3 | 4 | By building around a visual programming model, Ballerina allows you to connect apps and services and create any 5 | program via a sequence diagram. It’s a unique approach that we believe will make all of us faster and more effective 6 | at designing integration logic. 7 | 8 | At WSO2, we create open source integration middleware. Historically, integration has been about connecting systems together. 9 | The stuff that does this — which we build — has always been software glue; it brings a great deal of functionality to the table, 10 | sticks the important bits together and generally stayed out of the way. 11 | 12 | This model was built for an age when enterprises were basically collections of heavily customised, 13 | monolithic on-premise systems that had to work together. In today’s world, however, 14 | we have so many excellent pre-built systems — especially cloud services — that we now spend most our time composing 15 | systems out of pre-built blocks. There’s always a library or a service that you can just plug in there instead of 16 | reinventing the wheel. 17 | 18 | In this context, integration becomes part and parcel of the actual process of building systems. 19 | Connecting X to Y and making sure it works with Z is practically the real core of a developer’s workload. 20 | You’d think that we’d have built tools for this, but we haven’t. 21 | Our integration logic is largely done in languages meant for something else — Java, Python, and so on. 22 | This was why we decided to create a language meant for integration, and for integration only. 23 | Which brought us to the next problem: how would that work? 24 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/nativeimpl/WriteXml.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.nativeimpl; 20 | 21 | import io.ballerina.runtime.api.values.BObject; 22 | import io.ballerina.runtime.api.values.BXml; 23 | import io.ballerina.stdlib.io.channels.base.CharacterChannel; 24 | import io.ballerina.stdlib.io.utils.BallerinaIOException; 25 | import io.ballerina.stdlib.io.utils.IOConstants; 26 | import io.ballerina.stdlib.io.utils.IOUtils; 27 | 28 | /** 29 | * Writes XML to a given location. 30 | * 31 | * @since ballerina-0.970.0-alpha3 32 | */ 33 | public final class WriteXml { 34 | 35 | private WriteXml() {} 36 | 37 | public static Object writeXml(BObject characterChannelObj, BXml content) { 38 | try { 39 | CharacterChannel characterChannel = (CharacterChannel) characterChannelObj.getNativeData( 40 | IOConstants.CHARACTER_CHANNEL_NAME); 41 | IOUtils.writeFull(characterChannel, content.toString()); 42 | } catch (BallerinaIOException e) { 43 | return IOUtils.createError(e); 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /compiler-plugin/src/main/java/io/ballerina/stdlib/io/compiler/staticcodeanalyzer/IORule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.compiler.staticcodeanalyzer; 20 | 21 | import io.ballerina.scan.Rule; 22 | 23 | import static io.ballerina.scan.RuleKind.VULNERABILITY; 24 | import static io.ballerina.stdlib.io.compiler.staticcodeanalyzer.RuleFactory.createRule; 25 | 26 | /** 27 | * Represents static code rules specific to the Ballerina File package. 28 | */ 29 | public enum IORule { 30 | AVOID_PATH_TRAVERSAL(createRule(1, "I/O function calls should not be vulnerable to path" + 31 | " injection attacks", VULNERABILITY)); 32 | 33 | private final Rule rule; 34 | 35 | IORule(Rule rule) { 36 | this.rule = rule; 37 | } 38 | 39 | public int getId() { 40 | return this.rule.numericId(); 41 | } 42 | 43 | public Rule getRule() { 44 | return this.rule; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "{\"id\":" + this.getId() + ", \"kind\":\"" + this.rule.kind() + "\"," + 50 | " \"description\" : \"" + this.rule.description() + "\"}"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/TempFileIOChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.channels; 20 | 21 | import io.ballerina.stdlib.io.utils.IOUtils; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.nio.channels.FileChannel; 26 | 27 | /** 28 | * A file channel for temp file resources. Once the channel is closed, temp file will be deleted. 29 | * 30 | * @since 0.964.0 31 | */ 32 | public class TempFileIOChannel extends FileIOChannel { 33 | 34 | private String tempFilePath; 35 | 36 | public TempFileIOChannel(FileChannel channel, String tempFilePath) { 37 | super(channel); 38 | this.tempFilePath = tempFilePath; 39 | } 40 | 41 | @Override 42 | public void close() throws IOException { 43 | super.close(); 44 | if (tempFilePath != null && !tempFilePath.isEmpty()) { 45 | File tempFile = new File(tempFilePath); 46 | boolean isFileDeleted = tempFile.delete(); 47 | if (!isFileDeleted) { 48 | throw IOUtils.createError("temporary file deletion failure occurred while closing TempFileIOChannel! "); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/base/Representation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.channels.base; 20 | 21 | import io.ballerina.stdlib.io.utils.IOConstants; 22 | 23 | /** 24 | * Defines how the bytes will be represented for different data types. 25 | */ 26 | public enum Representation { 27 | /** 28 | * Represents a 64 bit value. 29 | */ 30 | BIT_64(8, Byte.SIZE), 31 | /** 32 | * Represents a 32 bit value. 33 | */ 34 | BIT_32(4, Byte.SIZE), 35 | /** 36 | * Represents a 16 bit value. 37 | */ 38 | BIT_16(2, Byte.SIZE), 39 | /** 40 | * Represents a variable value which does not have a size defined. 41 | */ 42 | VARIABLE(-1, IOConstants.PROTO_BUF_BASE), 43 | /** 44 | * If representation is none. 45 | */ 46 | NONE(-1, -1); 47 | 48 | private int numberOfBytes; 49 | 50 | private int base; 51 | 52 | Representation(int numberOfBytes, int base) { 53 | this.numberOfBytes = numberOfBytes; 54 | this.base = base; 55 | } 56 | 57 | public int getNumberOfBytes() { 58 | return numberOfBytes; 59 | } 60 | 61 | public int getBase() { 62 | return base; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ballerina/options.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Represents a file opening options for writing. 18 | # 19 | # + OVERWRITE - Overwrite(truncate the existing content) 20 | # + APPEND - Append to the existing content 21 | public enum FileWriteOption { 22 | OVERWRITE, 23 | APPEND 24 | } 25 | 26 | # Represents the XML entity type that needs to be written. 27 | # 28 | # + DOCUMENT_ENTITY - An XML document with a single root node 29 | # + EXTERNAL_PARSED_ENTITY - Externally parsed well-formed XML entity 30 | public enum XmlEntityType { 31 | DOCUMENT_ENTITY, 32 | EXTERNAL_PARSED_ENTITY 33 | } 34 | 35 | # Represents the XML DOCTYPE entity. 36 | # 37 | # + system - The system identifier 38 | # + public - The public identifier 39 | # + internalSubset - Internal DTD schema 40 | public type XmlDoctype record {| 41 | string? system = (); 42 | string? 'public = (); 43 | string? internalSubset = (); 44 | |}; 45 | 46 | # Represents the writing options of an XML. 47 | # 48 | # + xmlEntityType - The entity type of the XML input (the default value is `DOCUMENT_ENTITY`) 49 | # + doctype - XML DOCTYPE value (the default value is `()`) 50 | public type XmlWriteOptions record {| 51 | XmlEntityType xmlEntityType = DOCUMENT_ENTITY; 52 | XmlDoctype? doctype = (); 53 | |}; 54 | -------------------------------------------------------------------------------- /examples/csv-processor/main.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/io; 18 | import ballerina/lang.'float; 19 | 20 | public function main() returns error? { 21 | 22 | stream performanceDataStream = check io:fileReadCsvAsStream("resources/grpc_performance_output.csv"); 23 | _ = check performanceDataStream.next(); // Skip the header 24 | 25 | float totalRunningTime = 0.0; 26 | int numberOfEntries = 0; 27 | int successCases = 0; 28 | int failureCases = 0; 29 | 30 | _ = check from string[] entry in performanceDataStream 31 | do { 32 | if entry.length() >= 2 { 33 | float|error duration = 'float:fromString(entry[0]); 34 | totalRunningTime += duration is float ? duration : 0.0; 35 | numberOfEntries += 1; 36 | 37 | if "OK".equalsIgnoreCaseAscii(entry[1]) { 38 | successCases += 1; 39 | } else { 40 | failureCases += 1; 41 | } 42 | } 43 | }; 44 | 45 | io:println(`Average running time : ${totalRunningTime / numberOfEntries}`); 46 | io:println(`No. of success cases: ${successCases}`); 47 | io:println(`No. of failure cases: ${failureCases}`); 48 | } 49 | -------------------------------------------------------------------------------- /ballerina/tests/conversion_io.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/test; 17 | 18 | @test:Config {} 19 | isolated function testStrToJsonConvert() returns error? { 20 | string content = "{\n" + " \"test\": { \"name\": \"Foo\" }\n" + "}"; 21 | json expectedJson = {test: {name: "Foo"}}; 22 | json result = check getJson(content, "UTF-8"); 23 | test:assertEquals(result, expectedJson); 24 | } 25 | 26 | @test:Config {} 27 | isolated function testXmlToJsonConvert() returns error? { 28 | string content = "" + "Foo" + ""; 29 | xml expectedXml = xml `Foo`; 30 | xml? result = check getXml(content, "UTF-8"); 31 | test:assertTrue(result is xml); 32 | test:assertEquals(result, expectedXml); 33 | } 34 | 35 | isolated function getJson(string content, string encoding) returns json|error { 36 | StringReader reader = new StringReader(content, encoding); 37 | var readResult = reader.readJson(); 38 | check reader.close(); 39 | return readResult; 40 | } 41 | 42 | isolated function getXml(string content, string encoding) returns xml?|error { 43 | StringReader reader = new StringReader(content, encoding); 44 | var readResult = reader.readXml(); 45 | check reader.close(); 46 | return readResult; 47 | } 48 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/base/IOChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | * 18 | */ 19 | 20 | package io.ballerina.stdlib.io.channels.base; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * Represents channel interface to develop io apis. 26 | */ 27 | public interface IOChannel { 28 | /** 29 | *

30 | * Specified whether the channel has reached it's end. 31 | *

32 | * 33 | * @return true if the channel has reached it's end. 34 | */ 35 | boolean hasReachedEnd(); 36 | 37 | /** 38 | *

39 | * Returns the byte channel interface. 40 | *

41 | * 42 | * @return byte channel. 43 | */ 44 | Channel getChannel(); 45 | 46 | /** 47 | *

48 | * Specifies the id of the channel. 49 | *

50 | * 51 | * @return unique id of the underlying byte channel. 52 | */ 53 | int id(); 54 | 55 | /** 56 | *

57 | * Close the channel. 58 | *

59 | * 60 | * @throws IOException during i/o error. 61 | */ 62 | void close() throws IOException; 63 | 64 | /** 65 | * Specifies whether there're remaining content on user-space. 66 | * 67 | * @return true if there're remaining content false if not. 68 | */ 69 | boolean remaining(); 70 | } 71 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/utils/Base64ByteChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.utils; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.nio.ByteBuffer; 24 | import java.nio.channels.ByteChannel; 25 | import java.nio.channels.Channels; 26 | import java.nio.channels.ReadableByteChannel; 27 | 28 | /** 29 | * Represent the byte channel that needs to be encode or decode using Base64 encoding scheme. 30 | * 31 | * @since 0.970.0 32 | */ 33 | public class Base64ByteChannel implements ByteChannel { 34 | private InputStream inputStream; 35 | private ReadableByteChannel byteChannel; 36 | 37 | public Base64ByteChannel(InputStream inputStream) { 38 | this.inputStream = inputStream; 39 | this.byteChannel = Channels.newChannel(inputStream); 40 | } 41 | 42 | @Override 43 | public int read(ByteBuffer dst) throws IOException { 44 | return byteChannel.read(dst); 45 | } 46 | 47 | @Override 48 | public int write(ByteBuffer src) throws IOException { 49 | return 0; 50 | } 51 | 52 | @Override 53 | public boolean isOpen() { 54 | return byteChannel.isOpen(); 55 | } 56 | 57 | @Override 58 | public void close() throws IOException { 59 | byteChannel.close(); 60 | inputStream.close(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /load-tests/csv_processor/src/app.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/io; 18 | import ballerina/lang.'float; 19 | import ballerina/http; 20 | 21 | service http:Service /BalPerformance on new http:Listener(9090) { 22 | 23 | resource function get grpc() returns json|error { 24 | stream performanceDataStream = check io:fileReadCsvAsStream("resources/ghz_output.csv"); 25 | _ = check performanceDataStream.next(); // Skip the header 26 | 27 | float totalRunningTime = 0.0; 28 | int numberOfEntries = 0; 29 | int successCases = 0; 30 | int failureCases = 0; 31 | 32 | check performanceDataStream.forEach(function(string[] entry) { 33 | if entry.length() >= 2 { 34 | float|error duration = 'float:fromString(entry[0]); 35 | totalRunningTime += duration is float ? duration : 0.0; 36 | numberOfEntries += 1; 37 | 38 | if "OK".equalsIgnoreCaseAscii(entry[1]) { 39 | successCases += 1; 40 | } else { 41 | failureCases += 1; 42 | } 43 | } 44 | }); 45 | 46 | return { 47 | "Average running time": (totalRunningTime / numberOfEntries), 48 | "No. of success cases": successCases, 49 | "No. of failure cases": failureCases 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/6.3/userguide/multi_project_builds.html 8 | */ 9 | 10 | pluginManagement { 11 | plugins { 12 | id "com.github.spotbugs" version "${spotbugsPluginVersion}" 13 | id "com.github.johnrengelman.shadow" version "${shadowJarPluginVersion}" 14 | id "de.undercouch.download" version "${downloadPluginVersion}" 15 | id "net.researchgate.release" version "${releasePluginVersion}" 16 | id "io.ballerina.plugin" version "${ballerinaGradlePluginVersion}" 17 | } 18 | 19 | repositories { 20 | gradlePluginPortal() 21 | maven { 22 | url = 'https://maven.pkg.github.com/ballerina-platform/*' 23 | credentials { 24 | username System.getenv("packageUser") 25 | password System.getenv("packagePAT") 26 | } 27 | } 28 | } 29 | } 30 | 31 | plugins { 32 | id "com.gradle.enterprise" version "3.13.2" 33 | } 34 | 35 | rootProject.name = 'io' 36 | 37 | include ':checkstyle' 38 | include ':io-native' 39 | include ':io-test-utils' 40 | include ':io-ballerina' 41 | include ':io-examples' 42 | include 'io-compiler-plugin' 43 | include 'io-compiler-plugin-tests' 44 | 45 | project(':checkstyle').projectDir = file("build-config${File.separator}checkstyle") 46 | project(':io-native').projectDir = file('native') 47 | project(':io-test-utils').projectDir = file('test-utils') 48 | project(':io-ballerina').projectDir = file('ballerina') 49 | project(':io-examples').projectDir = file('examples') 50 | project(':io-compiler-plugin').projectDir = file('compiler-plugin') 51 | project(':io-compiler-plugin-tests').projectDir = file('compiler-plugin-tests') 52 | 53 | gradleEnterprise { 54 | buildScan { 55 | termsOfServiceUrl = 'https://gradle.com/terms-of-service' 56 | termsOfServiceAgree = 'yes' 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/nativeimpl/ReadlnAny.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | package io.ballerina.stdlib.io.nativeimpl; 19 | 20 | import io.ballerina.runtime.api.Environment; 21 | import io.ballerina.runtime.api.creators.ErrorCreator; 22 | import io.ballerina.runtime.api.utils.StringUtils; 23 | import io.ballerina.runtime.api.values.BString; 24 | 25 | import java.io.PrintStream; 26 | import java.nio.charset.Charset; 27 | import java.util.Scanner; 28 | import java.util.concurrent.CompletableFuture; 29 | 30 | /** 31 | * Extern function ballerina/io:readln. 32 | * 33 | * @since 0.97 34 | */ 35 | public class ReadlnAny { 36 | 37 | private static final Scanner sc = new Scanner(System.in, Charset.defaultCharset().displayName()); 38 | private static final PrintStream printStream = System.out; 39 | 40 | private ReadlnAny() {} 41 | 42 | public static BString readln(Environment env, Object result) { 43 | if (result != null) { 44 | printStream.print(result); 45 | } 46 | return env.yieldAndRun(() -> { 47 | CompletableFuture future = new CompletableFuture<>(); 48 | Thread.startVirtualThread(() -> future.complete(StringUtils.fromString(sc.nextLine()))); 49 | try { 50 | return future.get(); 51 | } catch (Throwable e) { 52 | throw ErrorCreator.createError(e); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/readers/CharacterChannelReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.readers; 20 | 21 | import io.ballerina.stdlib.io.channels.base.CharacterChannel; 22 | import io.ballerina.stdlib.io.utils.BallerinaIOException; 23 | 24 | import java.io.IOException; 25 | import java.io.Reader; 26 | 27 | /** 28 | * This sub class of {@link Reader} use to convert {@link CharacterChannel} to Reader instance. 29 | */ 30 | public class CharacterChannelReader extends Reader { 31 | 32 | private CharacterChannel channel; 33 | 34 | public CharacterChannelReader(CharacterChannel channel) { 35 | this.channel = channel; 36 | } 37 | 38 | @Override 39 | public int read(char[] cbuf, int off, int len) throws IOException { 40 | if (!channel.hasReachedEnd()) { 41 | String content; 42 | try { 43 | content = channel.read(len); 44 | if (!content.isEmpty()) { 45 | final char[] chars = content.toCharArray(); 46 | System.arraycopy(chars, 0, cbuf, off, chars.length); 47 | return chars.length; 48 | } 49 | } catch (BallerinaIOException e) { 50 | throw new IOException(e); 51 | } 52 | } 53 | return -1; 54 | } 55 | 56 | @Override 57 | public void close() throws IOException { 58 | channel.close(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/bow/main.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/io; 18 | import ballerina/lang.array; 19 | import ballerina/regex; 20 | 21 | public function main() returns error? { 22 | // Read lines as a stream 23 | stream lineStream = check io:fileReadLinesAsStream("./resources/data.txt"); 24 | 25 | // Generating the bag-of-word (BoW) model 26 | map bow = {}; 27 | check lineStream.forEach(function(string line) { 28 | string[] tokens = regex:split(line, "\\s+"); 29 | foreach string token in tokens { 30 | if token != "" { 31 | string lowerCaseToken = token.toLowerAscii(); 32 | int? frequency = bow[lowerCaseToken]; 33 | bow[lowerCaseToken] = frequency is int ? frequency + 1 : 1; 34 | } 35 | } 36 | }); 37 | 38 | // Finding the most frequent number of words based on a given input 39 | int threshold = check 'int:fromString(io:readln("Enter the number of most frequent words to retrieve: ")); 40 | int[] vocabEntries = bow.toArray(); 41 | if threshold > vocabEntries.length() { 42 | threshold = vocabEntries.length(); 43 | } 44 | int thresholdBoundry = bow.toArray().sort(array:DESCENDING)[threshold - 1]; 45 | map frequentWords = bow.filter(function(int f) returns boolean { 46 | return f >= thresholdBoundry; 47 | }); 48 | 49 | io:println(`Most frequent ${threshold} words are:`); 50 | io:println(frequentWords); 51 | } 52 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/FileIOChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.channels.base.Channel; 21 | import io.ballerina.stdlib.io.utils.IOUtils; 22 | 23 | import java.io.IOException; 24 | import java.nio.channels.FileChannel; 25 | import java.nio.channels.WritableByteChannel; 26 | 27 | /** 28 | *

29 | * Represents the channel to perform I/O operations on file. 30 | *

31 | */ 32 | public class FileIOChannel extends Channel { 33 | 34 | /** 35 | * Maintains the file channel implementation. 36 | */ 37 | private FileChannel channel; 38 | 39 | public FileIOChannel(FileChannel channel) { 40 | super(channel); 41 | this.channel = channel; 42 | } 43 | 44 | /** 45 | * Transfer file content to the specified destination. 46 | *

47 | * {@inheritDoc} 48 | */ 49 | @Override 50 | public void transfer(int position, int count, WritableByteChannel dstChannel) { 51 | try { 52 | channel.transferTo(position, count, dstChannel); 53 | } catch (IOException e) { 54 | throw IOUtils.createError("error occurred while transferring file: " + e.getMessage()); 55 | } 56 | } 57 | 58 | @Override 59 | public Channel getChannel() { 60 | throw new UnsupportedOperationException(); 61 | } 62 | 63 | @Override 64 | public boolean remaining() { 65 | return false; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/channels/TempFileIOChannelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.util.TestUtil; 21 | import org.testng.Assert; 22 | import org.testng.annotations.BeforeSuite; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.channels.ByteChannel; 28 | import java.nio.channels.FileChannel; 29 | import java.nio.file.Files; 30 | import java.nio.file.Paths; 31 | 32 | /** 33 | * The unit test of the TempFileIOChannel class. 34 | */ 35 | public class TempFileIOChannelTest { 36 | 37 | private String currentDirectoryPath = "/tmp/"; 38 | 39 | @BeforeSuite 40 | public void setup() { 41 | 42 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 43 | } 44 | 45 | @Test(description = "Test creation and deletion of TempFileIOChannel") 46 | public void closeWithDeletion() throws IOException, URISyntaxException { 47 | 48 | String resourceFilePath = currentDirectoryPath + "tempFile1.txt"; 49 | Files.createFile(Paths.get(resourceFilePath)); 50 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 51 | TempFileIOChannel tempFileIOChannel = new TempFileIOChannel((FileChannel) readByteChannel, resourceFilePath); 52 | 53 | tempFileIOChannel.close(); 54 | Assert.assertFalse(Files.exists(Paths.get(resourceFilePath))); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/AbstractNativeChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.runtime.api.creators.ValueCreator; 21 | import io.ballerina.runtime.api.values.BObject; 22 | import io.ballerina.stdlib.io.channels.base.Channel; 23 | import io.ballerina.stdlib.io.utils.IOConstants; 24 | 25 | import static io.ballerina.stdlib.io.utils.IOUtils.getIOPackage; 26 | 27 | /** 28 | *

29 | * For I/O APIs to work it requires each I/O source (file,tcp socket) to return a generic ByteChannel. 30 | *

31 | *

32 | * This will prepare the ByteChannel to perform I/O operations. 33 | *

34 | */ 35 | public abstract class AbstractNativeChannel { 36 | /** 37 | * The struct type of the byte channel. 38 | */ 39 | private static final String READ_BYTE_CHANNEL_STRUCT = "ReadableByteChannel"; 40 | /** 41 | * Writable byte channel struct. 42 | */ 43 | private static final String WRITE_BYTE_CHANNEL_STRUCT = "WritableByteChannel"; 44 | 45 | protected static BObject createChannel(Channel channel) { 46 | BObject channelObj; 47 | if (channel.isReadable()) { 48 | channelObj = ValueCreator.createObjectValue(getIOPackage(), READ_BYTE_CHANNEL_STRUCT); 49 | } else { 50 | channelObj = ValueCreator.createObjectValue(getIOPackage(), WRITE_BYTE_CHANNEL_STRUCT); 51 | } 52 | channelObj.addNativeData(IOConstants.BYTE_CHANNEL_NAME, channel); 53 | return channelObj; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/util/Base64ByteChannelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.util; 19 | 20 | import io.ballerina.stdlib.io.utils.Base64ByteChannel; 21 | import org.testng.Assert; 22 | import org.testng.annotations.BeforeSuite; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.ByteBuffer; 28 | import java.nio.charset.StandardCharsets; 29 | import java.nio.file.Files; 30 | import java.nio.file.Path; 31 | import java.nio.file.Paths; 32 | 33 | /** 34 | * The unit test of the Base64ByteChannel class. 35 | */ 36 | public class Base64ByteChannelTest { 37 | 38 | private String currentDirectoryPath = "/tmp/"; 39 | 40 | @BeforeSuite 41 | public void setup() { 42 | 43 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 44 | } 45 | 46 | @Test(description = "Test creation and deletion of Base64ByteChannelTest") 47 | public void write() throws IOException, URISyntaxException { 48 | 49 | Path resourceFilePath = Paths.get(currentDirectoryPath + "base64File1.txt"); 50 | Files.write(resourceFilePath, "123456".getBytes(StandardCharsets.UTF_8)); 51 | Base64ByteChannel base64ByteChannel = new Base64ByteChannel(Files.newInputStream(resourceFilePath)); 52 | ByteBuffer byteBuffer = ByteBuffer.allocate(10); 53 | Assert.assertEquals(base64ByteChannel.read(byteBuffer), 6); 54 | Assert.assertEquals(base64ByteChannel.write(byteBuffer), 0); 55 | base64ByteChannel.close(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /ballerina/README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | This module provides file read/write APIs and console print/read APIs. The file APIs allow read and write operations on different kinds of file types such as bytes, text, CSV, JSON, and XML. Further, these file APIs can be categorized as streaming and non-streaming APIs. 4 | 5 | The following diagram depicts the overview architecture of the I/O package. 6 | 7 | ![Architecture Diagram](https://raw.githubusercontent.com/ballerina-platform/module-ballerina-io/master/ballerina/docs/architecture.svg) 8 | 9 | The file I/O operations can be categorized further based on the serialization and deserialization types such as: 10 | - Bytes I/O 11 | - Strings I/O 12 | - CSV I/O 13 | - JSON I/O 14 | - XML I/O 15 | 16 | ### Console I/O 17 | The console I/O APIs, which help you to read from the console as well as write to the console are as follows. 18 | - `io:print` 19 | - `io:println` 20 | - `io:readln` 21 | 22 | ### Bytes I/O 23 | The bytes I/O APIs provide the reading and writing APIs in both streaming and non-streaming ways. Those APIs are, 24 | - `io:fileReadBytes` 25 | - `io:fileReadBlocksAsStream` 26 | - `io:fileWriteBytes` 27 | - `io:fileWriteBlocksFromStream` 28 | 29 | ### Strings I/O 30 | The strings I/O APIs provide the reading and writing APIs in 3 different ways: 31 | 1. Read the complete file content as a string and write a given string to a file 32 | 2. Read the complete file content as a set of lines and write a given set of lines to a file 33 | 3. Read the complete file content as a stream of lines and write a given stream of lines to a file 34 | 35 | The strings I/O APIs are as follows: 36 | - `io:fileReadString` 37 | - `io:fileReadLines` 38 | - `io:fileReadLinesAsStream` 39 | - `io:fileWriteLines` 40 | - `io:fileWriteLinesFromStream` 41 | 42 | ### CSV I/O 43 | The CSV I/O APIs provide the reading and writing APIs in both streaming and non-streaming ways. Those APIs are: 44 | - `io:fileReadCsv` 45 | - `io:fileReadCsvAsStream` 46 | - `io:fileWriteCsv` 47 | - `io:fileWriteCsvFromStream` 48 | 49 | ### JSON I/O 50 | The JSON I/O APIs provide the reading and writing APIs for JSON content. Those APIs are: 51 | - `io:fileReadJson` 52 | - `io:fileWriteJson` 53 | 54 | ### XML I/O 55 | The XML I/O APIs provide the reading and writing APIs for XML content. Those APIs are: 56 | - `io:fileReadXml` 57 | - `io:fileWriteXml` 58 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/nativeimpl/PrintUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.nativeimpl; 20 | 21 | import io.ballerina.runtime.api.utils.StringUtils; 22 | 23 | import java.io.PrintStream; 24 | 25 | /** 26 | * This class will hold all utility functionalities that require to print to StdOut. 27 | * 28 | * @since 1.0.5 29 | */ 30 | public class PrintUtils { 31 | 32 | private PrintUtils() { 33 | } 34 | 35 | public static void print(long printOptionFile, Object... values) { 36 | 37 | PrintStream out; 38 | if (printOptionFile == 2) { 39 | out = System.err; 40 | } else { 41 | out = System.out; 42 | } 43 | if (values == null) { 44 | out.print((Object) null); 45 | return; 46 | } 47 | for (Object value : values) { 48 | if (value != null) { 49 | out.print(StringUtils.getStringValue(value, null)); 50 | } 51 | } 52 | } 53 | 54 | public static void println(long printOptionFile, Object... values) { 55 | 56 | PrintStream out; 57 | if (printOptionFile == 2) { 58 | out = System.err; 59 | } else { 60 | out = System.out; 61 | } 62 | if (values == null) { 63 | out.println((Object) null); 64 | return; 65 | } 66 | StringBuilder content = new StringBuilder(); 67 | for (Object value : values) { 68 | if (value != null) { 69 | content.append(StringUtils.getStringValue(value, null)); 70 | } 71 | } 72 | out.println(content); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ballerina/types.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerina/jballerina.java; 18 | 19 | # The iterator for the stream returned in `readFileCsvAsStream` function. 20 | public class CsvIterator { 21 | private boolean isClosed = false; 22 | public isolated function next() returns record {|anydata value;|}|error? { 23 | if self.isClosed { 24 | return closedStreamInvocationError(); 25 | } else { 26 | record{}|string[]|Error? result = nextResult(self); 27 | if result is record{} || result is string[] { 28 | return {value: result}; 29 | } else if result is EofError { 30 | self.isClosed = true; 31 | check closeResult(self); 32 | return; 33 | } else { 34 | return result; 35 | } 36 | } 37 | } 38 | 39 | public isolated function close() returns Error? { 40 | if !self.isClosed { 41 | var closeResult = closeResult(self); 42 | if closeResult is () { 43 | self.isClosed = true; 44 | } 45 | return closeResult; 46 | } 47 | return; 48 | } 49 | } 50 | 51 | isolated function nextResult(CsvIterator iterator) returns record{}|string[]|Error? = @java:Method { 52 | name: "streamNext", 53 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 54 | } external; 55 | 56 | isolated function closeResult(CsvIterator iterator) returns Error? = @java:Method { 57 | name: "closeStream", 58 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 59 | } external; 60 | 61 | isolated function closedStreamInvocationError() returns Error { 62 | return error GenericError("Stream closed"); 63 | } 64 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/util/JBallerinaTestInitializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.util; 20 | 21 | import org.testng.ITestContext; 22 | import org.testng.ITestListener; 23 | import org.testng.ITestResult; 24 | 25 | /** 26 | * A test suit listener for jballerina test cases initialization. 27 | * 28 | * @since 0.995.0 29 | */ 30 | public class JBallerinaTestInitializer implements ITestListener { 31 | 32 | private static final String ENABLE_JBALLERINA_TESTS = "enableJBallerinaTests"; 33 | 34 | @Override 35 | public void onStart(ITestContext context) { 36 | String property = context.getCurrentXmlTest().getParameter(ENABLE_JBALLERINA_TESTS); 37 | if (property != null && Boolean.valueOf(property)) { 38 | System.setProperty(ENABLE_JBALLERINA_TESTS, "true"); 39 | } 40 | } 41 | 42 | @Override 43 | public void onFinish(ITestContext context) { 44 | String property = context.getCurrentXmlTest().getParameter(ENABLE_JBALLERINA_TESTS); 45 | if (property != null && Boolean.valueOf(property)) { 46 | System.clearProperty(ENABLE_JBALLERINA_TESTS); 47 | } 48 | } 49 | 50 | @Override 51 | public void onTestStart(ITestResult result) { 52 | //ignore 53 | } 54 | 55 | @Override 56 | public void onTestSuccess(ITestResult result) { 57 | //ignore 58 | } 59 | 60 | @Override 61 | public void onTestFailure(ITestResult result) { 62 | //ignore 63 | } 64 | 65 | @Override 66 | public void onTestSkipped(ITestResult result) { 67 | //ignore 68 | } 69 | 70 | @Override 71 | public void onTestFailedButWithinSuccessPercentage(ITestResult result) { 72 | //ignore 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/salesforce/main.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | import ballerinax/salesforce; 18 | import ballerinax/salesforce.bulk as sbulk; 19 | import ballerina/log; 20 | import ballerina/io; 21 | 22 | json accountRecord = { 23 | Name: "WSO2", 24 | BillingCity: "Colombo 00300" 25 | }; 26 | 27 | configurable string BASE_URL = ?; 28 | configurable string SF_TOKEN = ?; 29 | 30 | public function main() returns error? { 31 | salesforce:ConnectionConfig sfConfig = { 32 | baseUrl: BASE_URL, 33 | clientConfig: { 34 | token: SF_TOKEN 35 | } 36 | }; 37 | stream csvStream = check io:fileReadCsvAsStream("resources/data.csv"); 38 | sbulk:Client baseClient = check new (sfConfig); 39 | sbulk:BulkJob queryJob = check baseClient->createJob("insert", "Contact", "CSV"); 40 | 41 | do { 42 | sbulk:BatchInfo batch = check baseClient->addBatch(queryJob, csvStream); 43 | string batchId = batch.id; 44 | 45 | // Get batch info 46 | sbulk:BatchInfo batchInfo = check baseClient->getBatchInfo(queryJob, batchId); 47 | log:printInfo(string `Batch processing state: ${batchInfo.state}`); 48 | 49 | // Get batch result 50 | sbulk:Result[] batchResult = check baseClient->getBatchResult(queryJob, batchId); 51 | foreach sbulk:Result res in batchResult { 52 | if !res.success { 53 | log:printError("Operation failed", result = (res.errors is string ? res.errors : "")); 54 | } 55 | } 56 | 57 | // Close the job 58 | _ = check baseClient->closeJob(queryJob); 59 | } on fail error err { 60 | log:printError("Salesforce batch operation failed", 'error = err); 61 | _ = check baseClient->closeJob(queryJob); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/channels/BlobChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import java.io.IOException; 21 | import java.nio.ByteBuffer; 22 | import java.nio.channels.ByteChannel; 23 | import java.nio.channels.ReadableByteChannel; 24 | import java.nio.channels.WritableByteChannel; 25 | 26 | /** 27 | * Creates channel which will reference byte content. 28 | */ 29 | public class BlobChannel implements ByteChannel { 30 | 31 | private ReadableByteChannel readableChannel; 32 | private WritableByteChannel writableChannel; 33 | 34 | public BlobChannel(ReadableByteChannel channel) { 35 | this.readableChannel = channel; 36 | } 37 | 38 | public BlobChannel(WritableByteChannel channel) { 39 | this.writableChannel = channel; 40 | } 41 | 42 | @Override 43 | public int read(ByteBuffer dst) throws IOException { 44 | if (readableChannel == null) { 45 | throw new UnsupportedOperationException(); 46 | } 47 | return readableChannel.read(dst); 48 | } 49 | 50 | @Override 51 | public int write(ByteBuffer src) throws IOException { 52 | if (writableChannel == null) { 53 | throw new UnsupportedOperationException(); 54 | } 55 | return this.writableChannel.write(src); 56 | } 57 | 58 | @Override 59 | public boolean isOpen() { 60 | if (readableChannel != null) { 61 | return readableChannel.isOpen(); 62 | } else { 63 | return writableChannel.isOpen(); 64 | } 65 | } 66 | 67 | @Override 68 | public void close() throws IOException { 69 | if (readableChannel != null) { 70 | readableChannel.close(); 71 | } else { 72 | writableChannel.close(); 73 | } 74 | } 75 | 76 | public boolean isReadable() { 77 | return readableChannel != null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /ballerina/constants.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Specifies the format used to represent CSV data. 18 | # 19 | # DEFAULT - The default value is the format specified by the CSVChannel. Precedence will be given to the field 20 | # separator and record separator. 21 | # 22 | # CSV - Field separator will be "," and the record separator will be a new line. 23 | # 24 | # TDF - Field separator will be a tab and the record separator will be a new line. 25 | public type Format DEFAULT|CSV|TDF; 26 | 27 | # The default value is the format specified by the CSVChannel. Precedence will be given to the field separator and record separator. 28 | public const DEFAULT = "default"; 29 | 30 | # Field separator will be "," and the record separator will be a new line. 31 | public const CSV = "csv"; 32 | 33 | # Field separator will be a tab and the record separator will be a new line. 34 | public const TDF = "tdf"; 35 | 36 | # Field separators, which are supported by the `DelimitedTextRecordChannel`. 37 | # 38 | # COMMA - Delimited text records will be separated using a comma 39 | # 40 | # TAB - Delimited text records will be separated using a tab 41 | # 42 | # COLON - Delimited text records will be separated using a colon(:) 43 | public type Separator COMMA|TAB|COLON|string; 44 | 45 | # Comma (,) will be used as the field separator. 46 | public const COMMA = ","; 47 | 48 | # Tab (/t) will be use as the field separator. 49 | public const TAB = "\t"; 50 | 51 | # Colon (:) will be use as the field separator. 52 | public const COLON = ":"; 53 | 54 | # New line character. 55 | public const NEW_LINE = "\n"; 56 | 57 | # Single space character. 58 | const SINGLE_SPACE = " "; 59 | 60 | # Double quote character. 61 | const DOUBLE_QUOTE = "\""; 62 | 63 | # Default encoding for the abstract read/write APIs. 64 | public const DEFAULT_ENCODING = "UTF8"; 65 | 66 | # Represents the standard output stream. 67 | public const stdout = 1; 68 | 69 | # Represents the standard error stream. 70 | public const stderr = 2; 71 | -------------------------------------------------------------------------------- /native/src/main/java/io/ballerina/stdlib/io/csv/Format.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.csv; 20 | 21 | /** 22 | * Holds the format which should be supported for CSV. 23 | */ 24 | public enum Format { 25 | /** 26 | * The format would default, however empty lines will be allowed. 27 | */ 28 | DEFAULT(",", "\\r?\\n", ",", "\n", false), 29 | /** 30 | * CSV should conform with RFC4180 specification. 31 | */ 32 | CSV(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", "\\r?\\n", ",", "\n", true), 33 | /** 34 | * Tab delimited records. 35 | */ 36 | TDF("\\t", "\\r?\\n", "\t", "\n", false); 37 | 38 | /** 39 | * Defines the record separator for the format. 40 | */ 41 | private String readRecSeparator; 42 | /** 43 | * Defines the field separator for the format. 44 | */ 45 | private String readFieldSeparator; 46 | /** 47 | * Defines the record separator which should be used when writing. 48 | */ 49 | private String writeRecSeparator; 50 | /** 51 | * Defines the field separator which should be used when writing. 52 | */ 53 | private String writeFieldSeparator; 54 | /** 55 | * Specifies whether to ignore blanks. 56 | */ 57 | private boolean ignoreBlanks; 58 | 59 | Format(String rfs, String rrs, String wfs, String wrs, boolean ignoreBlank) { 60 | this.readFieldSeparator = rfs; 61 | this.readRecSeparator = rrs; 62 | this.writeFieldSeparator = wfs; 63 | this.writeRecSeparator = wrs; 64 | this.ignoreBlanks = ignoreBlank; 65 | } 66 | 67 | public String getReadRecSeparator() { 68 | return readRecSeparator; 69 | } 70 | 71 | public String getReadFieldSeparator() { 72 | return readFieldSeparator; 73 | } 74 | 75 | public String getWriteRecSeparator() { 76 | return writeRecSeparator; 77 | } 78 | 79 | public String getWriteFieldSeparator() { 80 | return writeFieldSeparator; 81 | } 82 | 83 | public boolean shouldIgnoreBlanks() { 84 | return ignoreBlanks; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /ballerina/writable_byte_channel.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # Represents a writable byte channel that acts as an output resource (e.g., a file) for writing bytes. 19 | # A file path can be used to obtain an `io:WritableByteChannel`. 20 | # 21 | # `io:openWritableFile("./files/sample.txt")` - used to obtain an `io:WritableByteChannel` from a given file path 22 | public class WritableByteChannel { 23 | 24 | # Adding default init function to prevent object getting initialized from the user code. 25 | isolated function init() { 26 | } 27 | 28 | # Sinks bytes from a given input/output resource. 29 | # 30 | # This is an asynchronous operation. The method might return before writing all the content. 31 | # ```ballerina 32 | # int|io:Error result = writableByteChannel.write(record, 0); 33 | # ``` 34 | # 35 | # + content - Block of bytes to be written 36 | # + offset - Offset of the provided content, which needs to be kept when writing bytes 37 | # + return - Number of bytes written or else an `io:Error` 38 | public isolated function write(byte[] content, int offset) returns int|Error { 39 | return byteWriteExtern(self, content, offset); 40 | } 41 | 42 | # Closes the byte channel. 43 | # After a channel is closed, any further writing operations will cause an error. 44 | # ```ballerina 45 | # io:Error err = writableByteChannel.close(); 46 | # ``` 47 | # 48 | # + return - `()` or else an `io:Error` if any error occurred 49 | public isolated function close() returns Error? { 50 | return closeWritableByteChannelExtern(self); 51 | } 52 | } 53 | 54 | isolated function byteWriteExtern(WritableByteChannel byteChannel, byte[] content, int offset) returns int|Error = @java:Method { 55 | name: "write", 56 | 'class: "io.ballerina.stdlib.io.nativeimpl.ByteChannelUtils" 57 | } external; 58 | 59 | isolated function closeWritableByteChannelExtern(WritableByteChannel byteChannel) returns Error? = @java:Method { 60 | name: "closeByteChannel", 61 | 'class: "io.ballerina.stdlib.io.nativeimpl.ByteChannelUtils" 62 | } external; 63 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/util/TestUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | * 18 | */ 19 | 20 | package io.ballerina.stdlib.io.util; 21 | 22 | import java.io.IOException; 23 | import java.net.URISyntaxException; 24 | import java.net.URL; 25 | import java.nio.channels.ByteChannel; 26 | import java.nio.file.Files; 27 | import java.nio.file.OpenOption; 28 | import java.nio.file.Path; 29 | import java.nio.file.Paths; 30 | import java.nio.file.StandardOpenOption; 31 | import java.util.HashSet; 32 | import java.util.Set; 33 | 34 | /** 35 | * Contains the util functions related to I/O test cases. 36 | */ 37 | public final class TestUtil { 38 | 39 | private TestUtil() {} 40 | 41 | /** 42 | * Opens a channel from a specified file. 43 | * 44 | * @param filePath the path to the file. 45 | * @return the file channel. 46 | * @throws IOException during I/O error. 47 | * @throws URISyntaxException during failure to validate uri syntax. 48 | */ 49 | public static ByteChannel openForReading(String filePath) throws IOException, URISyntaxException { 50 | Set opts = new HashSet<>(); 51 | opts.add(StandardOpenOption.READ); 52 | URL fileResource = TestUtil.class.getClassLoader().getResource(filePath); 53 | ByteChannel channel = null; 54 | if (null != fileResource) { 55 | Path path = Paths.get(fileResource.toURI()); 56 | channel = Files.newByteChannel(path, opts); 57 | } 58 | return channel; 59 | } 60 | 61 | /** 62 | * Opens a file for writing. 63 | * 64 | * @param filePath the path the file should be opened for writing. 65 | * @return the writable channel. 66 | * @throws IOException during I/O error. 67 | */ 68 | public static ByteChannel openForReadingAndWriting(String filePath) throws IOException { 69 | Set opts = new HashSet<>(); 70 | opts.add(StandardOpenOption.CREATE); 71 | opts.add(StandardOpenOption.WRITE); 72 | opts.add(StandardOpenOption.READ); 73 | Path path = Paths.get(filePath); 74 | return Files.newByteChannel(path, opts); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /compiler-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) 3 | * 4 | * WSO2 LLC. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | plugins { 20 | id 'java' 21 | id 'checkstyle' 22 | id 'com.github.spotbugs' 23 | } 24 | 25 | description = 'Ballerina - IO Compiler Plugin' 26 | 27 | 28 | dependencies { 29 | checkstyle project(':checkstyle') 30 | checkstyle "com.puppycrawl.tools:checkstyle:${checkstylePluginVersion}" 31 | 32 | implementation group: 'org.ballerinalang', name: 'ballerina-lang', version: "${ballerinaLangVersion}" 33 | implementation group: 'org.ballerinalang', name: 'ballerina-tools-api', version: "${ballerinaLangVersion}" 34 | implementation group: 'org.ballerinalang', name: 'ballerina-parser', version: "${ballerinaLangVersion}" 35 | implementation group: 'io.ballerina.scan', name: 'scan-command', version: "${balScanVersion}" 36 | implementation project(":io-native") 37 | } 38 | 39 | def excludePattern = '**/module-info.java' 40 | tasks.withType(Checkstyle) { 41 | exclude excludePattern 42 | } 43 | 44 | checkstyle { 45 | toolVersion "${project.checkstylePluginVersion}" 46 | configFile rootProject.file("build-config/checkstyle/build/checkstyle.xml") 47 | configProperties = ["suppressionFile" : file("${rootDir}/build-config/checkstyle/build/suppressions.xml")] 48 | } 49 | 50 | checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") 51 | 52 | spotbugsMain { 53 | def classLoader = plugins["com.github.spotbugs"].class.classLoader 54 | def SpotBugsConfidence = classLoader.findLoadedClass("com.github.spotbugs.snom.Confidence") 55 | def SpotBugsEffort = classLoader.findLoadedClass("com.github.spotbugs.snom.Effort") 56 | effort = SpotBugsEffort.MAX 57 | reportLevel = SpotBugsConfidence.LOW 58 | reportsDir = file("$project.buildDir/reports/spotbugs") 59 | reports { 60 | html.enabled true 61 | text.enabled = true 62 | } 63 | def excludeFile = file("${rootDir}/spotbugs-exclude.xml") 64 | if(excludeFile.exists()) { 65 | excludeFilter = excludeFile 66 | } 67 | } 68 | 69 | compileJava { 70 | doFirst { 71 | options.compilerArgs = [ 72 | '--module-path', classpath.asPath, 73 | ] 74 | classpath = files() 75 | } 76 | } 77 | 78 | build.dependsOn ":io-native:build" -------------------------------------------------------------------------------- /examples/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import org.apache.tools.ant.taskdefs.condition.Os 20 | 21 | apply plugin: 'java' 22 | 23 | description = 'Ballerina - I/O Examples' 24 | 25 | def ballerinaDist = "${project.rootDir}/target/ballerina-runtime" 26 | def examples = ["csv-processor"] 27 | 28 | task testExamples { 29 | doLast { 30 | examples.each { example -> 31 | def exampleDirectory = "${project.projectDir}/${example}" 32 | try { 33 | exec { 34 | workingDir exampleDirectory 35 | if (Os.isFamily(Os.FAMILY_WINDOWS)) { 36 | commandLine 'cmd', '/c', "${ballerinaDist}/bin/bal.bat run --offline && exit %%ERRORLEVEL%%" 37 | } else { 38 | commandLine 'sh', '-c', "${ballerinaDist}/bin/bal run --offline" 39 | } 40 | } 41 | } catch (Exception e) { 42 | println("Example '${example}' Build failed: " + e.message) 43 | throw e 44 | } 45 | } 46 | } 47 | } 48 | 49 | task buildExamples { 50 | gradle.taskGraph.whenReady { graph -> 51 | if (graph.hasTask(":io-examples:test")) { 52 | buildExamples.enabled = false 53 | } else { 54 | testExamples.enabled = false 55 | } 56 | } 57 | doLast { 58 | examples.each { example -> 59 | try { 60 | exec { 61 | workingDir project.projectDir 62 | if (Os.isFamily(Os.FAMILY_WINDOWS)) { 63 | commandLine 'cmd', '/c', "${ballerinaDist}/bin/bal.bat build ${example} && exit %%ERRORLEVEL%%" 64 | } else { 65 | commandLine 'sh', '-c', "${ballerinaDist}/bin/bal build ${example}" 66 | } 67 | } 68 | } catch (Exception e) { 69 | println("Example '${example}' Build failed: " + e.message) 70 | throw e 71 | } 72 | } 73 | } 74 | } 75 | 76 | testExamples.dependsOn ":io-ballerina:build" 77 | buildExamples.dependsOn ":io-ballerina:build" 78 | test.dependsOn testExamples 79 | build.dependsOn buildExamples 80 | -------------------------------------------------------------------------------- /ballerina/line_stream.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # A stream of strings(lines) that is used to read the character content from the streams. 19 | public class LineStream { 20 | private ReadableCharacterChannel readableCharacterChannel; 21 | private boolean isClosed = false; 22 | 23 | # Initializes A stream of strings(lines). 24 | # 25 | # + readableCharacterChannel - The `io:ReadableCharacterChannel` that the line stream is referred to 26 | public isolated function init(ReadableCharacterChannel readableCharacterChannel) { 27 | self.readableCharacterChannel = readableCharacterChannel; 28 | } 29 | 30 | # Reads the next line of the stream. 31 | # 32 | # + return - A line as a string when a line is available in the stream or returns `()` when the stream reaches the end 33 | public isolated function next() returns record {|string value;|}|Error? { 34 | var line = readLine(self.readableCharacterChannel); 35 | if line is string { 36 | record {|string value;|} value = {value: line.cloneReadOnly()}; 37 | return value; 38 | } else if line is EofError { 39 | check closeReader(self.readableCharacterChannel); 40 | return; 41 | } else { 42 | return line; 43 | } 44 | } 45 | 46 | # Closes the stream manually. 47 | # If not invoked, the stream closes automatically upon reaching end-of-stream. 48 | # 49 | # + return - `()` when the closing was successful or an `io:Error` 50 | public isolated function close() returns Error? { 51 | if !self.isClosed { 52 | var closeResult = closeReader(self.readableCharacterChannel); 53 | if closeResult is () { 54 | self.isClosed = true; 55 | } 56 | return closeResult; 57 | } 58 | return; 59 | } 60 | } 61 | 62 | isolated function readLine(ReadableCharacterChannel readableCharacterChannel) returns string|Error = @java:Method { 63 | name: "readLine", 64 | 'class: "io.ballerina.stdlib.io.nativeimpl.CharacterChannelUtils" 65 | } external; 66 | 67 | isolated function closeReader(ReadableCharacterChannel readableCharacterChannel) returns Error? = @java:Method { 68 | name: "closeBufferedReader", 69 | 'class: "io.ballerina.stdlib.io.nativeimpl.CharacterChannelUtils" 70 | } external; 71 | -------------------------------------------------------------------------------- /ballerina/file_byte_io.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Reads the entire file content as a byte array. 18 | # ```ballerina 19 | # byte[]|io:Error content = io:fileReadBytes("./resources/myfile.txt"); 20 | # ``` 21 | # + path - The file path 22 | # + return - A read-only byte array or an `io:Error` 23 | public isolated function fileReadBytes(string path) returns readonly & byte[]|Error { 24 | return channelReadBytes(check openReadableFile(path)); 25 | } 26 | 27 | # Reads the entire file content as a stream of blocks. 28 | # ```ballerina 29 | # stream|io:Error content = io:fileReadBlocksAsStream("./resources/myfile.txt", 1000); 30 | # ``` 31 | # + path - The file path 32 | # + blockSize - An optional size of the byte block. The default size is 4KB 33 | # + return - A byte block stream or an `io:Error` 34 | public isolated function fileReadBlocksAsStream(string path, int blockSize = 4096) returns stream| 35 | Error { 36 | return channelReadBlocksAsStream(check openReadableFile(path), blockSize); 37 | } 38 | 39 | # Writes a set of bytes to a file. 40 | # ```ballerina 41 | # byte[] content = [60, 78, 39, 28]; 42 | # io:Error? result = io:fileWriteBytes("./resources/myfile.txt", content); 43 | # ``` 44 | # + path - The file path 45 | # + content - Byte content to write 46 | # + option - Indicate whether to overwrite or append the given content 47 | # + return - An `io:Error` if the write operation fails, or () 48 | public isolated function fileWriteBytes(string path, byte[] content, FileWriteOption option = OVERWRITE) returns 49 | Error? { 50 | return channelWriteBytes(check openWritableFile(path, option), content); 51 | } 52 | 53 | # Writes a byte stream to a file. 54 | # ```ballerina 55 | # byte[] content = [[60, 78, 39, 28]]; 56 | # stream byteStream = content.toStream(); 57 | # io:Error? result = io:fileWriteBlocksFromStream("./resources/myfile.txt", byteStream); 58 | # ``` 59 | # + path - The file path 60 | # + byteStream - Byte stream to write 61 | # + option - Indicate whether to overwrite or append the given content 62 | # + return - An `io:Error` if the write operation fails, or () 63 | public isolated function fileWriteBlocksFromStream(string path, stream byteStream, 64 | FileWriteOption option = OVERWRITE) returns Error? { 65 | return channelWriteBlocksFromStream(check openWritableFile(path, option), byteStream); 66 | } 67 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/channels/BlobIOChannelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.util.TestUtil; 21 | import org.testng.Assert; 22 | import org.testng.annotations.BeforeSuite; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.channels.ByteChannel; 28 | import java.nio.channels.ReadableByteChannel; 29 | 30 | /** 31 | * The unit test of the BlobIOChannel class. 32 | */ 33 | public class BlobIOChannelTest { 34 | 35 | private String currentDirectoryPath = "/tmp/"; 36 | 37 | @BeforeSuite 38 | public void setup() { 39 | 40 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 41 | } 42 | 43 | @Test(expectedExceptions = UnsupportedOperationException.class) 44 | public void transfer() throws IOException, URISyntaxException { 45 | 46 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 47 | String destinationFilePath = currentDirectoryPath + "blobIoChannel1.txt"; 48 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 49 | ByteChannel writeByteChannel = TestUtil.openForReadingAndWriting(destinationFilePath); 50 | BlobIOChannel blobIoChannel = new BlobIOChannel(new BlobChannel((ReadableByteChannel) readByteChannel)); 51 | 52 | blobIoChannel.transfer(0, 5, writeByteChannel); 53 | } 54 | 55 | @Test(expectedExceptions = UnsupportedOperationException.class) 56 | public void getChannel() throws IOException, URISyntaxException { 57 | 58 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 59 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 60 | BlobIOChannel blobIoChannel = new BlobIOChannel(new BlobChannel((ReadableByteChannel) readByteChannel)); 61 | blobIoChannel.getChannel(); 62 | } 63 | 64 | @Test(description = "Test remaining API of BlobIOChannelTest") 65 | public void remaining() throws IOException, URISyntaxException { 66 | 67 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 68 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 69 | BlobIOChannel blobIoChannel = new BlobIOChannel(new BlobChannel((ReadableByteChannel) readByteChannel)); 70 | Assert.assertFalse(blobIoChannel.remaining()); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /ballerina/csv_stream.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # A stream of CSV records that is used to read the CSV content from the streams. 19 | public class CSVStream { 20 | private ReadableTextRecordChannel readableTextRecordChannel; 21 | private boolean isClosed = false; 22 | 23 | # Initializes a stream of CSV records. 24 | # 25 | # + readableTextRecordChannel - The `io:ReadableTextRecordChannel` that this CSV stream is referred to 26 | public isolated function init(ReadableTextRecordChannel readableTextRecordChannel) { 27 | self.readableTextRecordChannel = readableTextRecordChannel; 28 | } 29 | 30 | # Reads the next CSV record of the stream. 31 | # 32 | # + return - A CSV record as a string array when a record is available in the stream or 33 | # `()` when the stream reaches the end 34 | public isolated function next() returns record {|string[] value;|}|Error? { 35 | var recordValue = readRecord(self.readableTextRecordChannel); 36 | if recordValue is string[] { 37 | record {|string[] value;|} value = {value: recordValue.cloneReadOnly()}; 38 | return value; 39 | } else if recordValue is EofError { 40 | check closeRecordReader(self.readableTextRecordChannel); 41 | return; 42 | } else { 43 | return recordValue; 44 | } 45 | } 46 | 47 | # Closes the stream manually. 48 | # If not invoked, the stream closes automatically upon reaching end-of-stream. 49 | # 50 | # + return - `()` when the closing was successful or an `io:Error` 51 | public isolated function close() returns Error? { 52 | if !self.isClosed { 53 | var closeResult = closeRecordReader(self.readableTextRecordChannel); 54 | if closeResult is () { 55 | self.isClosed = true; 56 | } 57 | return closeResult; 58 | } 59 | return; 60 | } 61 | } 62 | 63 | isolated function readRecord(ReadableTextRecordChannel readableTextRecordChannel) returns string[]| 64 | Error = @java:Method { 65 | name: "readRecord", 66 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 67 | } external; 68 | 69 | isolated function closeRecordReader(ReadableTextRecordChannel readableTextRecordChannel) returns Error? = @java:Method { 70 | name: "closeBufferedReader", 71 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 72 | } external; 73 | -------------------------------------------------------------------------------- /test-utils/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | apply plugin: "java" 19 | apply plugin: "com.github.spotbugs" 20 | apply plugin: "checkstyle" 21 | 22 | description = 'Ballerina - IO Java Utils' 23 | 24 | dependencies { 25 | implementation group: 'org.ballerinalang', name: 'ballerina-lang', version: "${ballerinaLangVersion}" 26 | implementation group: 'org.ballerinalang', name: 'ballerina-runtime', version: "${ballerinaLangVersion}" 27 | implementation project(":io-native") 28 | 29 | checkstyle project(":checkstyle") 30 | checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleToolVersion}" 31 | } 32 | 33 | spotbugsMain { 34 | def classLoader = plugins["com.github.spotbugs"].class.classLoader 35 | def SpotBugsConfidence = classLoader.findLoadedClass("com.github.spotbugs.snom.Confidence") 36 | def SpotBugsEffort = classLoader.findLoadedClass("com.github.spotbugs.snom.Effort") 37 | ignoreFailures = true 38 | effort = SpotBugsEffort.MAX 39 | reportLevel = SpotBugsConfidence.LOW 40 | reportsDir = file("$project.buildDir/reports/spotbugs") 41 | def excludeFile = file("${rootDir}/build-config/spotbugs-exclude.xml") 42 | if (excludeFile.exists()) { 43 | it.excludeFilter = excludeFile 44 | } 45 | reports { 46 | text.enabled = true 47 | } 48 | } 49 | 50 | spotbugsTest { 51 | enabled = false 52 | } 53 | 54 | task validateSpotbugs() { 55 | doLast { 56 | if (spotbugsMain.reports.size() > 0 && 57 | spotbugsMain.reports[0].destination.exists() && 58 | spotbugsMain.reports[0].destination.text.readLines().size() > 0) { 59 | spotbugsMain.reports[0].destination?.eachLine { 60 | println 'Failure: ' + it 61 | } 62 | throw new GradleException("Spotbugs rule violations were found."); 63 | } 64 | } 65 | } 66 | 67 | checkstyle { 68 | toolVersion '7.8.2' 69 | configFile file("${rootDir}/build-config/checkstyle/build/checkstyle.xml") 70 | configProperties = ["suppressionFile": file("${rootDir}/build-config/checkstyle/build/suppressions.xml")] 71 | } 72 | 73 | tasks.withType(Checkstyle) { 74 | exclude '**/module-info.java' 75 | } 76 | 77 | spotbugsMain.finalizedBy validateSpotbugs 78 | checkstyleMain.dependsOn ":checkstyle:downloadCheckstyleRuleFiles" 79 | 80 | compileJava { 81 | doFirst { 82 | options.compilerArgs = [ 83 | '--module-path', classpath.asPath, 84 | ] 85 | classpath = files() 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /ballerina/channel_byte_io.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/lang.'value; 17 | 18 | isolated function channelReadBytes(ReadableChannel readableChannel) returns readonly & byte[]|Error { 19 | if readableChannel is ReadableByteChannel { 20 | var result = readableChannel.readAll(); 21 | check readableChannel.close(); 22 | return result; 23 | } else { 24 | TypeMismatchError e = error TypeMismatchError("Expected ReadableByteChannel but found a " + 'value:toString(typeof 25 | readableChannel)); 26 | return e; 27 | } 28 | } 29 | 30 | isolated function channelReadBlocksAsStream(ReadableChannel readableChannel, int blockSize = 4096) returns stream< 31 | Block, Error?>|Error { 32 | if readableChannel is ReadableByteChannel { 33 | return readableChannel.blockStream(blockSize); 34 | } else { 35 | TypeMismatchError e = error TypeMismatchError("Expected ReadableByteChannel but found a " + 'value:toString(typeof 36 | readableChannel)); 37 | return e; 38 | } 39 | } 40 | 41 | isolated function channelWriteBytes(WritableChannel writableChannel, byte[] content) returns Error? { 42 | if writableChannel is WritableByteChannel { 43 | do { 44 | _ = check writableChannel.write(content, 0); 45 | check writableChannel.close(); 46 | } on fail Error err { 47 | check writableChannel.close(); 48 | return err; 49 | } 50 | } else { 51 | TypeMismatchError e = error TypeMismatchError("Expected WritableByteChannel but found a " + 'value:toString(typeof 52 | writableChannel)); 53 | return e; 54 | } 55 | return; 56 | } 57 | 58 | isolated function channelWriteBlocksFromStream(WritableChannel writableChannel, stream byteStream) returns 59 | Error? { 60 | if writableChannel is WritableByteChannel { 61 | do { 62 | record {|byte[] value;|}|Error? block = byteStream.next(); 63 | while block is record {|byte[] value;|} { 64 | _ = check writableChannel.write(block.value, 0); 65 | block = byteStream.next(); 66 | } 67 | check writableChannel.close(); 68 | } on fail Error err { 69 | check writableChannel.close(); 70 | return err; 71 | } 72 | } else { 73 | TypeMismatchError e = error TypeMismatchError("Expected WritableByteChannel but found a " + 'value:toString(typeof 74 | writableChannel)); 75 | return e; 76 | } 77 | return; 78 | } 79 | -------------------------------------------------------------------------------- /ballerina/block_stream.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # The read-only byte array that is used to read the byte content from the streams. 19 | public type Block readonly & byte[]; 20 | 21 | # A stream of `Block` objects that is used to read the byte content from the streams. 22 | public class BlockStream { 23 | private ReadableByteChannel readableByteChannel; 24 | private int blockSize; 25 | private boolean isClosed = false; 26 | 27 | # Initializes a stream of `Block` objects. 28 | # 29 | # + readableByteChannel - The `io:ReadableByteChannel` that this block stream is referred to 30 | # + blockSize - The size of a block as an integer 31 | public isolated function init(ReadableByteChannel readableByteChannel, int blockSize) { 32 | self.readableByteChannel = readableByteChannel; 33 | self.blockSize = blockSize; 34 | } 35 | 36 | # Reads the next block of the stream. 37 | # 38 | # + return - An `io:Block` when a block is available in the stream or returns `()` when the stream reaches the end 39 | public isolated function next() returns record {|Block value;|}|Error? { 40 | byte[]|Error block = readBlock(self.readableByteChannel, self.blockSize); 41 | if block is byte[] { 42 | record {|Block value;|} value = {value: block.cloneReadOnly()}; 43 | return value; 44 | } else if block is EofError { 45 | return closeInputStream(self.readableByteChannel); 46 | } else { 47 | return block; 48 | } 49 | } 50 | 51 | # Closes the stream manually. 52 | # If not invoked, the stream closes automatically upon reaching end-of-stream. 53 | # 54 | # + return - `()` when the closing was successful or an `io:Error` 55 | public isolated function close() returns Error? { 56 | if !self.isClosed { 57 | var closeResult = closeInputStream(self.readableByteChannel); 58 | if closeResult is () { 59 | self.isClosed = true; 60 | } 61 | return closeResult; 62 | } 63 | return; 64 | } 65 | } 66 | 67 | isolated function readBlock(ReadableByteChannel readableByteChannel, int blockSize) returns byte[]|Error = @java:Method { 68 | name: "readBlock", 69 | 'class: "io.ballerina.stdlib.io.nativeimpl.ByteChannelUtils" 70 | } external; 71 | 72 | isolated function closeInputStream(ReadableByteChannel readableByteChannel) returns Error? = @java:Method { 73 | name: "closeInputStream", 74 | 'class: "io.ballerina.stdlib.io.nativeimpl.ByteChannelUtils" 75 | } external; 76 | -------------------------------------------------------------------------------- /test-utils/src/main/java/io/ballerina/stdlib/io/testutils/PrintTestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.testutils; 20 | 21 | import io.ballerina.runtime.api.utils.StringUtils; 22 | import io.ballerina.runtime.api.values.BString; 23 | import io.ballerina.stdlib.io.utils.Utils; 24 | 25 | import java.io.ByteArrayOutputStream; 26 | import java.io.PrintStream; 27 | import java.nio.charset.Charset; 28 | 29 | /** 30 | * PrintUtils to read the console and return the output. 31 | */ 32 | public class PrintTestUtils { 33 | 34 | private static final Object outLock = new Object(); 35 | private static final Object errLock = new Object(); 36 | static ByteArrayOutputStream outContent; 37 | static ByteArrayOutputStream errContent; 38 | 39 | private PrintTestUtils() { 40 | } 41 | 42 | // Initialize output stream 43 | public static void initOutputStream() { 44 | 45 | synchronized (outLock) { 46 | if (outContent == null) { 47 | outContent = new ByteArrayOutputStream(); 48 | System.setOut(new PrintStream(outContent, false, Charset.defaultCharset())); 49 | } 50 | } 51 | } 52 | 53 | // Initialize error stream 54 | public static void initErrorStream() { 55 | 56 | synchronized (errLock) { 57 | if (errContent == null) { 58 | errContent = new ByteArrayOutputStream(); 59 | System.setErr(new PrintStream(errContent, false, Charset.defaultCharset())); 60 | } 61 | } 62 | } 63 | 64 | // Read output stream and return it as a ballerina string 65 | public static BString readOutputStream() { 66 | 67 | return StringUtils.fromString(outContent.toString(Charset.defaultCharset()).replace("\r", "")); 68 | } 69 | 70 | // Read error stream and return it as a ballerina string 71 | public static BString readErrorStream() { 72 | 73 | return StringUtils.fromString(errContent.toString(Charset.defaultCharset()).replace("\r", "")); 74 | } 75 | 76 | // Reset output stream 77 | public static void resetOutputStream() { 78 | 79 | if (outContent != null) { 80 | outContent.reset(); 81 | } 82 | } 83 | 84 | // Reset error stream 85 | public static void resetErrorStream() { 86 | 87 | if (errContent != null) { 88 | errContent.reset(); 89 | } 90 | } 91 | 92 | public static Object base64Encode(Object input, BString charset, boolean mimeSpecific) { 93 | return Utils.encode(input, charset.getValue(), mimeSpecific); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ballerina/writable_csv_channel.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Represents the record separator of the CSV file. 18 | public const string CSV_RECORD_SEPARATOR = "\n"; 19 | 20 | # Represents the colon separator, which should be used to identify colon-separated files. 21 | public const string FS_COLON = ":"; 22 | 23 | # Represents the minimum number of headers, which will be included in the CSV. 24 | public const int MINIMUM_HEADER_COUNT = 0; 25 | 26 | # Represents a writable CSV channel, which could be used to write records from the CSV file. 27 | public class WritableCSVChannel { 28 | private WritableTextRecordChannel? dc; 29 | 30 | # Initializes a writable CSV channel. 31 | # 32 | # + CharacterChannel - The `io:WritableCharacterChannel`, which will represent the content in the CSV file 33 | # + fs - The field separator, which will separate the records in the CSV 34 | public isolated function init(WritableCharacterChannel characterChannel, Separator fs = ",") { 35 | if fs == TAB { 36 | self.dc = new WritableTextRecordChannel(characterChannel, fmt = "TDF"); 37 | } else if fs == COLON { 38 | self.dc = new WritableTextRecordChannel(characterChannel, FS_COLON, CSV_RECORD_SEPARATOR); 39 | } else if fs == COMMA { 40 | self.dc = new WritableTextRecordChannel(characterChannel, fmt = "CSV"); 41 | } else { 42 | self.dc = new WritableTextRecordChannel(characterChannel, fs, CSV_RECORD_SEPARATOR); 43 | } 44 | } 45 | 46 | # Writes the record to a given CSV file. 47 | # ```ballerina 48 | # io:Error err = csvChannel.write(record); 49 | # ``` 50 | # 51 | # + csvRecord - A record to be written to the channel 52 | # + return - An `io:Error` if the record could not be written properly 53 | public isolated function write(string[] csvRecord) returns Error? { 54 | if self.dc is WritableTextRecordChannel { 55 | var result = self.dc; 56 | return result.write(csvRecord); 57 | } 58 | return; 59 | } 60 | 61 | # Closes the writable CSV channel. 62 | # After a channel is closed, any further writing operations will cause an error. 63 | # ```ballerina 64 | # io:Error? err = csvChannel.close(); 65 | # ``` 66 | # 67 | # + return - `()` or else an `io:Error` if any error occurred 68 | public isolated function close() returns Error? { 69 | if self.dc is WritableTextRecordChannel { 70 | var result = self.dc; 71 | return result.close(); 72 | } 73 | return; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/channels/FileIOChannelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.util.TestUtil; 21 | import org.testng.Assert; 22 | import org.testng.annotations.BeforeSuite; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.channels.ByteChannel; 28 | import java.nio.channels.FileChannel; 29 | import java.nio.charset.StandardCharsets; 30 | import java.nio.file.Files; 31 | import java.nio.file.Paths; 32 | 33 | /** 34 | * The unit test of the FileIOChannel class. 35 | */ 36 | public class FileIOChannelTest { 37 | 38 | private String currentDirectoryPath = "/tmp/"; 39 | 40 | @BeforeSuite 41 | public void setup() { 42 | 43 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 44 | } 45 | 46 | @Test(description = "Test data transferring of FileIOChannelTest") 47 | public void transfer() throws IOException, URISyntaxException { 48 | 49 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 50 | String destinationFilePath = currentDirectoryPath + "fileIOChannel1.txt"; 51 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 52 | ByteChannel writeByteChannel = TestUtil.openForReadingAndWriting(destinationFilePath); 53 | FileIOChannel fileIOChannel = new FileIOChannel((FileChannel) readByteChannel); 54 | 55 | fileIOChannel.transfer(0, 5, writeByteChannel); 56 | String content = Files.readString(Paths.get(destinationFilePath), StandardCharsets.UTF_8); 57 | Assert.assertEquals(content, "12345"); 58 | } 59 | 60 | @Test(expectedExceptions = UnsupportedOperationException.class) 61 | public void getChannel() throws IOException, URISyntaxException { 62 | 63 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 64 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 65 | FileIOChannel fileIOChannel = new FileIOChannel((FileChannel) readByteChannel); 66 | fileIOChannel.getChannel(); 67 | } 68 | 69 | @Test(description = "Test remaining API of FileIOChannelTest") 70 | public void remaining() throws IOException, URISyntaxException { 71 | 72 | String resourceFilePath = "datafiles/io/text/charfile.txt"; 73 | ByteChannel readByteChannel = TestUtil.openForReading(resourceFilePath); 74 | FileIOChannel fileIOChannel = new FileIOChannel((FileChannel) readByteChannel); 75 | Assert.assertFalse(fileIOChannel.remaining()); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | This file contains all the notable changes done to the Ballerina I/O package through the releases. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | ## [Unreleased] 7 | ### Added 8 | - [Add static code rules](https://github.com/ballerina-platform/ballerina-library/issues/7283) 9 | 10 | ### Fixed 11 | - [The CSV file read as a record failed when a nillable field was empty](https://github.com/ballerina-platform/ballerina-library/issues/7433) 12 | 13 | ## [1.6.1] - 2024-08-06 14 | ### Changed 15 | - [Make some of the Java classes proper utility classes](https://github.com/ballerina-platform/ballerina-standard-library/issues/4901) 16 | - [Remove Error logger in module-ballerina-io](https://github.com/ballerina-platform/ballerina-standard-library/issues/3083) 17 | - [Remove architecture diagram from the resources directory](https://github.com/ballerina-platform/ballerina-library/issues/6832) 18 | 19 | ## [1.4.0] - 2023-02-20 20 | ### Changed 21 | - [Fixed the issue related to maintaining order in writing CSV records](https://github.com/ballerina-platform/ballerina-standard-library/issues/3399) 22 | - [Fixed the fileReadCsv and fileReadCsvAsStream APIs to maintain the order while reading CSV records](https://github.com/ballerina-platform/ballerina-standard-library/issues/3780) 23 | - [Fixed the issue related to expected type in CSV data mapping](https://github.com/ballerina-platform/ballerina-standard-library/issues/3669) 24 | 25 | ## [1.3.1] - 2022-11-29 26 | ### Changed 27 | - [API docs updated](https://github.com/ballerina-platform/ballerina-standard-library/issues/3463) 28 | 29 | ## [1.3.0] - 2022-09-08 30 | ### Added 31 | -[Add support for Data Mapping in CSV read/write operations](https://github.com/ballerina-platform/ballerina-standard-library/issues/2871) 32 | 33 | ### Fixed 34 | - [Add decimal suuport to toTable API](https://github.com/ballerina-platform/ballerina-standard-library/issues/2884) 35 | 36 | 37 | ## [1.0.0] - 2021-10-08 38 | ### Added 39 | - [Add support for reading quoted fields in fileReadCsvAsStream API](https://github.com/ballerina-platform/ballerina-standard-library/issues/1890) 40 | 41 | ### Fixed 42 | - [Introduce toTable API](https://github.com/ballerina-platform/ballerina-standard-library/issues/1871) 43 | 44 | 45 | ## [0.6.0-beta.2] - 2021-07-06 46 | ### Added 47 | - [Introduce fprint and fprintln APIs](https://github.com/ballerina-platform/ballerina-standard-library/issues/1394) 48 | 49 | ## [0.6.0-beta.1] - 2021-06-02 50 | ### Fixed 51 | - [Fixes the unexpected error return](https://github.com/ballerina-platform/ballerina-standard-library/issues/1316) 52 | - [Fixes the included and default parameter order in `io:fileWriteXml` API](https://github.com/ballerina-platform/ballerina-standard-library/issues/1346) 53 | 54 | ## [0.6.0-alpha6] - 2021-04-02 55 | ### Added 56 | - [Improve the print APIs to support raw templates](https://github.com/ballerina-platform/ballerina-standard-library/issues/1050). 57 | ```ballerina 58 | string val = "John"; 59 | io:println(`Hello ${val}!!!`); 60 | io:print(`Hello ${val}!!!`); 61 | ``` 62 | ### Changed 63 | - [Introduce nil completion to the I/O streams(lines, blocks, and CSV)](https://github.com/ballerina-platform/ballerina-standard-library/issues/1181). 64 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/characters/AsyncReadWriteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.characters; 20 | 21 | import io.ballerina.stdlib.io.MockByteChannel; 22 | import io.ballerina.stdlib.io.channels.base.Channel; 23 | import io.ballerina.stdlib.io.channels.base.CharacterChannel; 24 | import io.ballerina.stdlib.io.util.TestUtil; 25 | import org.testng.Assert; 26 | import org.testng.annotations.BeforeSuite; 27 | import org.testng.annotations.Test; 28 | 29 | import java.io.IOException; 30 | import java.nio.channels.ByteChannel; 31 | import java.nio.charset.StandardCharsets; 32 | 33 | /** 34 | * Represents the framework for reading writing characters using async io framework. 35 | */ 36 | public class AsyncReadWriteTest { 37 | /** 38 | * Specifies the default directory path. 39 | */ 40 | private String currentDirectoryPath = "/tmp/"; 41 | 42 | @BeforeSuite 43 | public void setup() { 44 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 45 | } 46 | 47 | @Test(description = "Tests reading characters through the async io framework") 48 | public void readCharacters() throws Exception { 49 | int numberOfCharactersToRead = 2; 50 | //Number of characters in this file would be 6 51 | ByteChannel byteChannel = TestUtil.openForReading("datafiles/io/text/longChars.txt"); 52 | Channel channel = new MockByteChannel(byteChannel); 53 | CharacterChannel characterChannel = new CharacterChannel(channel, StandardCharsets.UTF_8.name()); 54 | Assert.assertEquals("NJa", characterChannel.read(numberOfCharactersToRead)); 55 | 56 | numberOfCharactersToRead = 3; 57 | Assert.assertEquals("bcNJ", characterChannel.read(numberOfCharactersToRead)); 58 | 59 | numberOfCharactersToRead = 4; 60 | Assert.assertEquals("ff", characterChannel.read(numberOfCharactersToRead)); 61 | 62 | characterChannel.close(); 63 | } 64 | 65 | @Test(description = "Test writing characters through async io framework") 66 | public void writeCharacters() throws IOException { 67 | //Number of characters in this file would be 6 68 | ByteChannel byteChannel = TestUtil.openForReadingAndWriting(currentDirectoryPath + "write.txt"); 69 | Channel channel = new MockByteChannel(byteChannel); 70 | CharacterChannel characterChannel = new CharacterChannel(channel, StandardCharsets.UTF_8.name()); 71 | 72 | String text = "HelloNJ"; 73 | int numberOfBytes = text.getBytes().length; 74 | 75 | Assert.assertEquals(characterChannel.write(text, 0), numberOfBytes); 76 | characterChannel.close(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/util/UtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.util; 19 | 20 | import io.ballerina.runtime.api.values.BArray; 21 | import io.ballerina.stdlib.io.utils.Utils; 22 | import org.testng.Assert; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.charset.StandardCharsets; 28 | import java.util.Base64; 29 | 30 | /** 31 | * The unit test of the Utils class. 32 | */ 33 | public class UtilsTest { 34 | 35 | @Test(description = "Test encode and decode APIs of Utils") 36 | public void encodeAndDecodeString() throws IOException, URISyntaxException { 37 | 38 | String content = "Ballerina"; 39 | Object encodedContent = Utils.encodeString(content, StandardCharsets.UTF_8.displayName(), false); 40 | byte[] decodedValue = Base64.getMimeDecoder().decode(encodedContent.toString() 41 | .getBytes(StandardCharsets.ISO_8859_1)); 42 | Assert.assertEquals(new String(decodedValue, StandardCharsets.UTF_8.displayName()), content); 43 | } 44 | 45 | @Test(description = "Test encode and decode APIs of Utils with mime specified") 46 | public void encodeAndDecodeMimeString() throws IOException, URISyntaxException { 47 | 48 | String content = "Ballerina"; 49 | Object encodedContent = Utils.encodeString(content, StandardCharsets.UTF_8.displayName(), true); 50 | byte[] decodedValue = Base64.getMimeDecoder().decode(encodedContent.toString() 51 | .getBytes(StandardCharsets.ISO_8859_1)); 52 | Assert.assertEquals(new String(decodedValue, StandardCharsets.UTF_8.displayName()), content); 53 | } 54 | 55 | @Test(description = "Test encode and decode APIs of Utils") 56 | public void encodeAndDecodeBlob() throws IOException, URISyntaxException { 57 | 58 | String content = "Ballerina"; 59 | BArray encodedContent = Utils.encodeBlob(content.getBytes(StandardCharsets.UTF_8), false); 60 | BArray decodedContent = Utils.decodeBlob(encodedContent.getByteArray(), false); 61 | Assert.assertEquals(new String(decodedContent.getBytes()), content); 62 | } 63 | 64 | @Test(description = "Test encode and decode APIs of Utils with mime specified") 65 | public void encodeAndDecodeMimeBlob() throws IOException, URISyntaxException { 66 | 67 | String content = "Ballerina"; 68 | BArray encodedContent = Utils.encodeBlob(content.getBytes(StandardCharsets.UTF_8), true); 69 | BArray decodedContent = Utils.decodeBlob(encodedContent.getByteArray(), true); 70 | Assert.assertEquals(new String(decodedContent.getBytes()), content); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/util/Base64WrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.util; 19 | 20 | import io.ballerina.stdlib.io.utils.Base64ByteChannel; 21 | import io.ballerina.stdlib.io.utils.Base64Wrapper; 22 | import org.testng.Assert; 23 | import org.testng.annotations.BeforeSuite; 24 | import org.testng.annotations.Test; 25 | 26 | import java.io.IOException; 27 | import java.net.URISyntaxException; 28 | import java.nio.channels.ByteChannel; 29 | import java.nio.charset.StandardCharsets; 30 | import java.nio.file.Files; 31 | import java.nio.file.Path; 32 | import java.nio.file.Paths; 33 | 34 | /** 35 | * The unit test of the Base64Wrapper class. 36 | */ 37 | public class Base64WrapperTest { 38 | 39 | private String currentDirectoryPath = "/tmp/"; 40 | 41 | @BeforeSuite 42 | public void setup() { 43 | 44 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 45 | } 46 | 47 | @Test(expectedExceptions = UnsupportedOperationException.class) 48 | public void transfer() throws IOException, URISyntaxException { 49 | 50 | String resourceFile = currentDirectoryPath + "base64File2.txt"; 51 | Path resourceFilePath = Paths.get(resourceFile); 52 | Files.write(resourceFilePath, "123456".getBytes(StandardCharsets.UTF_8)); 53 | ByteChannel byteChannel = TestUtil.openForReadingAndWriting(resourceFile); 54 | Base64ByteChannel base64ByteChannel = new Base64ByteChannel(Files.newInputStream(resourceFilePath)); 55 | Base64Wrapper base64Wrapper = new Base64Wrapper(base64ByteChannel); 56 | base64Wrapper.transfer(0, 1, byteChannel); 57 | } 58 | 59 | @Test(expectedExceptions = UnsupportedOperationException.class) 60 | public void getChannel() throws IOException, URISyntaxException { 61 | 62 | String resourceFile = currentDirectoryPath + "base64File2.txt"; 63 | Path resourceFilePath = Paths.get(resourceFile); 64 | Files.write(resourceFilePath, "123456".getBytes(StandardCharsets.UTF_8)); 65 | Base64ByteChannel base64ByteChannel = new Base64ByteChannel(Files.newInputStream(resourceFilePath)); 66 | Base64Wrapper base64Wrapper = new Base64Wrapper(base64ByteChannel); 67 | base64Wrapper.getChannel(); 68 | } 69 | 70 | @Test(description = "Test remaining API of BlobIOChannelTest") 71 | public void remaining() throws IOException, URISyntaxException { 72 | 73 | String resourceFile = currentDirectoryPath + "base64File2.txt"; 74 | Path resourceFilePath = Paths.get(resourceFile); 75 | Files.write(resourceFilePath, "123456".getBytes(StandardCharsets.UTF_8)); 76 | Base64ByteChannel base64ByteChannel = new Base64ByteChannel(Files.newInputStream(resourceFilePath)); 77 | Base64Wrapper base64Wrapper = new Base64Wrapper(base64ByteChannel); 78 | Assert.assertFalse(base64Wrapper.remaining()); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /ballerina/Dependencies.toml: -------------------------------------------------------------------------------- 1 | # AUTO-GENERATED FILE. DO NOT MODIFY. 2 | 3 | # This file is auto-generated by Ballerina for managing dependency versions. 4 | # It should not be modified by hand. 5 | 6 | [ballerina] 7 | dependencies-toml-version = "2" 8 | distribution-version = "2201.12.0" 9 | 10 | [[package]] 11 | org = "ballerina" 12 | name = "io" 13 | version = "1.8.1" 14 | dependencies = [ 15 | {org = "ballerina", name = "jballerina.java"}, 16 | {org = "ballerina", name = "lang.float"}, 17 | {org = "ballerina", name = "lang.runtime"}, 18 | {org = "ballerina", name = "lang.string"}, 19 | {org = "ballerina", name = "lang.value"}, 20 | {org = "ballerina", name = "test"} 21 | ] 22 | modules = [ 23 | {org = "ballerina", packageName = "io", moduleName = "io"} 24 | ] 25 | 26 | [[package]] 27 | org = "ballerina" 28 | name = "jballerina.java" 29 | version = "0.0.0" 30 | modules = [ 31 | {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} 32 | ] 33 | 34 | [[package]] 35 | org = "ballerina" 36 | name = "lang.__internal" 37 | version = "0.0.0" 38 | scope = "testOnly" 39 | dependencies = [ 40 | {org = "ballerina", name = "jballerina.java"}, 41 | {org = "ballerina", name = "lang.object"} 42 | ] 43 | 44 | [[package]] 45 | org = "ballerina" 46 | name = "lang.array" 47 | version = "0.0.0" 48 | scope = "testOnly" 49 | dependencies = [ 50 | {org = "ballerina", name = "jballerina.java"}, 51 | {org = "ballerina", name = "lang.__internal"} 52 | ] 53 | 54 | [[package]] 55 | org = "ballerina" 56 | name = "lang.error" 57 | version = "0.0.0" 58 | scope = "testOnly" 59 | dependencies = [ 60 | {org = "ballerina", name = "jballerina.java"} 61 | ] 62 | 63 | [[package]] 64 | org = "ballerina" 65 | name = "lang.float" 66 | version = "0.0.0" 67 | scope = "testOnly" 68 | dependencies = [ 69 | {org = "ballerina", name = "jballerina.java"} 70 | ] 71 | modules = [ 72 | {org = "ballerina", packageName = "lang.float", moduleName = "lang.float"} 73 | ] 74 | 75 | [[package]] 76 | org = "ballerina" 77 | name = "lang.object" 78 | version = "0.0.0" 79 | scope = "testOnly" 80 | 81 | [[package]] 82 | org = "ballerina" 83 | name = "lang.regexp" 84 | version = "0.0.0" 85 | scope = "testOnly" 86 | dependencies = [ 87 | {org = "ballerina", name = "jballerina.java"} 88 | ] 89 | 90 | [[package]] 91 | org = "ballerina" 92 | name = "lang.runtime" 93 | version = "0.0.0" 94 | scope = "testOnly" 95 | dependencies = [ 96 | {org = "ballerina", name = "jballerina.java"} 97 | ] 98 | modules = [ 99 | {org = "ballerina", packageName = "lang.runtime", moduleName = "lang.runtime"} 100 | ] 101 | 102 | [[package]] 103 | org = "ballerina" 104 | name = "lang.string" 105 | version = "0.0.0" 106 | scope = "testOnly" 107 | dependencies = [ 108 | {org = "ballerina", name = "jballerina.java"}, 109 | {org = "ballerina", name = "lang.regexp"} 110 | ] 111 | modules = [ 112 | {org = "ballerina", packageName = "lang.string", moduleName = "lang.string"} 113 | ] 114 | 115 | [[package]] 116 | org = "ballerina" 117 | name = "lang.value" 118 | version = "0.0.0" 119 | dependencies = [ 120 | {org = "ballerina", name = "jballerina.java"} 121 | ] 122 | modules = [ 123 | {org = "ballerina", packageName = "lang.value", moduleName = "lang.value"} 124 | ] 125 | 126 | [[package]] 127 | org = "ballerina" 128 | name = "test" 129 | version = "0.0.0" 130 | scope = "testOnly" 131 | dependencies = [ 132 | {org = "ballerina", name = "jballerina.java"}, 133 | {org = "ballerina", name = "lang.array"}, 134 | {org = "ballerina", name = "lang.error"} 135 | ] 136 | modules = [ 137 | {org = "ballerina", packageName = "test", moduleName = "test"} 138 | ] 139 | 140 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/records/AsyncReadWriteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.ballerina.stdlib.io.records; 20 | 21 | import io.ballerina.stdlib.io.MockByteChannel; 22 | import io.ballerina.stdlib.io.channels.base.Channel; 23 | import io.ballerina.stdlib.io.channels.base.CharacterChannel; 24 | import io.ballerina.stdlib.io.channels.base.DelimitedRecordChannel; 25 | import io.ballerina.stdlib.io.util.TestUtil; 26 | import io.ballerina.stdlib.io.utils.BallerinaIOException; 27 | import org.testng.Assert; 28 | import org.testng.annotations.BeforeSuite; 29 | import org.testng.annotations.Test; 30 | 31 | import java.io.IOException; 32 | import java.net.URISyntaxException; 33 | import java.nio.channels.ByteChannel; 34 | import java.nio.charset.StandardCharsets; 35 | 36 | /** 37 | * Represents the framework for read/write delimited text records. 38 | */ 39 | public class AsyncReadWriteTest { 40 | /** 41 | * Specifies the default directory path. 42 | */ 43 | private String currentDirectoryPath = "/tmp/"; 44 | 45 | @BeforeSuite 46 | public void setup() { 47 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 48 | } 49 | 50 | @Test(description = "Test which will read text records from a given channel using async io framework") 51 | public void readTextRecords() throws IOException, URISyntaxException, BallerinaIOException { 52 | int expectedFieldCount = 3; 53 | //Number of characters in this file would be 6 54 | ByteChannel byteChannel = TestUtil.openForReading("datafiles/io/records/sample.csv"); 55 | Channel channel = new MockByteChannel(byteChannel); 56 | CharacterChannel characterChannel = new CharacterChannel(channel, StandardCharsets.UTF_8.name()); 57 | DelimitedRecordChannel recordChannel = new DelimitedRecordChannel(characterChannel, "\n", ","); 58 | Assert.assertEquals(recordChannel.read().length, expectedFieldCount); 59 | Assert.assertEquals(recordChannel.read().length, expectedFieldCount); 60 | Assert.assertEquals(recordChannel.read().length, expectedFieldCount); 61 | recordChannel.close(); 62 | } 63 | 64 | @Test(description = "Test which will write records to a channel using async io framework") 65 | public void writeRecords() throws IOException { 66 | //Number of characters in this file would be 6 67 | ByteChannel byteChannel = TestUtil.openForReadingAndWriting(currentDirectoryPath + "records.csv"); 68 | Channel channel = new MockByteChannel(byteChannel); 69 | CharacterChannel characterChannel = new CharacterChannel(channel, StandardCharsets.UTF_8.name()); 70 | DelimitedRecordChannel recordChannel = new DelimitedRecordChannel(characterChannel, "\n", ","); 71 | 72 | String[] recordOne = {"Foo", "Bar", "911"}; 73 | recordChannel.write(recordOne); 74 | 75 | String[] recordTwo = {"Jim", "Com", "119"}; 76 | recordChannel.write(recordTwo); 77 | recordChannel.close(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ballerina/writable_record_channel.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # Represents a writable text record channel that allows writing records. 19 | public class WritableTextRecordChannel { 20 | private WritableCharacterChannel characterChannel; 21 | private string fs; 22 | private string rs; 23 | 24 | # Initializes a writable text record channel. 25 | # + characterChannel - The `io:WritableCharacterChannel`, which will point to the input/output resource 26 | # + fs - The field separator (this could be a regex) 27 | # + rs - The record separator (this could be a regex) 28 | # + fmt - The format, which will be used to represent the CSV (this could be 29 | # "DEFAULT" (the format specified by the CSVChannel), 30 | # "CSV" (Field separator would be "," and record separator would be a new line) or else 31 | # "TDF" (Field separator will be a tab and record separator will be a new line) 32 | public isolated function init(WritableCharacterChannel characterChannel, string fs = "", string rs = "", 33 | string fmt = "default") { 34 | self.characterChannel = characterChannel; 35 | self.fs = fs; 36 | self.rs = rs; 37 | initWritableTextRecordChannel(self, characterChannel, fs, rs, fmt); 38 | } 39 | 40 | # Writes records to a given output resource. 41 | # ```ballerina 42 | # io:Error? err = writableChannel.write(records); 43 | # ``` 44 | # 45 | # + textRecord - List of fields to be written 46 | # + return - An `io:Error` if the records could not be written properly or else `()` 47 | public isolated function write(string[] textRecord) returns Error? { 48 | return writeRecordExtern(self, textRecord); 49 | } 50 | 51 | # Closes the record channel. 52 | # After a channel is closed, any further writing operations will cause an error. 53 | # ```ballerina 54 | # io:Error? err = writableChannel.close(); 55 | # ``` 56 | # 57 | # + return - An `io:Error` if the record channel could not be closed properly or else `()` 58 | public isolated function close() returns Error? { 59 | return closeWritableTextRecordChannelExtern(self); 60 | } 61 | } 62 | 63 | isolated function initWritableTextRecordChannel(WritableTextRecordChannel textChannel, 64 | WritableCharacterChannel charChannel, string fs, string rs, string fmt) = @java:Method { 65 | name: "initRecordChannel", 66 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 67 | } external; 68 | 69 | isolated function writeRecordExtern(WritableTextRecordChannel textChannel, string[] textRecord) returns Error? = @java:Method { 70 | name: "write", 71 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 72 | } external; 73 | 74 | isolated function closeWritableTextRecordChannelExtern(WritableTextRecordChannel textChannel) returns Error? = @java:Method { 75 | name: "close", 76 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 77 | } external; 78 | -------------------------------------------------------------------------------- /native/src/test/java/io/ballerina/stdlib/io/channels/BlobChannelTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | package io.ballerina.stdlib.io.channels; 19 | 20 | import io.ballerina.stdlib.io.util.TestUtil; 21 | import org.testng.Assert; 22 | import org.testng.annotations.BeforeSuite; 23 | import org.testng.annotations.Test; 24 | 25 | import java.io.IOException; 26 | import java.net.URISyntaxException; 27 | import java.nio.ByteBuffer; 28 | import java.nio.channels.ByteChannel; 29 | import java.nio.channels.ReadableByteChannel; 30 | import java.nio.channels.WritableByteChannel; 31 | 32 | /** 33 | * The unit test of the BlobChannel class. 34 | */ 35 | public class BlobChannelTest { 36 | 37 | private String currentDirectoryPath = "/tmp/"; 38 | 39 | @BeforeSuite 40 | public void setup() { 41 | 42 | currentDirectoryPath = System.getProperty("user.dir") + "/build/"; 43 | } 44 | 45 | @Test(description = "Test read and write operations of the BlobChannel") 46 | public void readAndWrite() throws IOException, URISyntaxException { 47 | 48 | ByteChannel readByteChannel = TestUtil.openForReading("datafiles/io/text/charfile.txt"); 49 | BlobChannel readBlobChannel = new BlobChannel((ReadableByteChannel) readByteChannel); 50 | ByteChannel writeByteChannel = TestUtil.openForReadingAndWriting(currentDirectoryPath + "blobChannel.txt"); 51 | BlobChannel writeBlobChannel = new BlobChannel((WritableByteChannel) writeByteChannel); 52 | char[] expectedArr = {'1', '2', '3', '4', '5', '6'}; 53 | int i = 0; 54 | 55 | ByteBuffer byteBuffer = ByteBuffer.allocate(30); 56 | Assert.assertTrue(readBlobChannel.isReadable()); 57 | Assert.assertEquals(readBlobChannel.read(byteBuffer), 6); 58 | ByteBuffer copyOfByteBuffer = byteBuffer.duplicate(); 59 | copyOfByteBuffer.flip(); 60 | byteBuffer.flip(); 61 | while (copyOfByteBuffer.hasRemaining()) { 62 | Assert.assertEquals((char) copyOfByteBuffer.get(), expectedArr[i]); 63 | i++; 64 | } 65 | readBlobChannel.close(); 66 | Assert.assertEquals(writeBlobChannel.write(byteBuffer), 6); 67 | writeBlobChannel.close(); 68 | } 69 | 70 | @Test(expectedExceptions = UnsupportedOperationException.class) 71 | public void readWithNull() throws IOException { 72 | 73 | BlobChannel blobChannel = new BlobChannel(getReadableByteChannel()); 74 | ByteBuffer byteBuffer = ByteBuffer.allocate(30); 75 | blobChannel.read(byteBuffer); 76 | } 77 | 78 | @Test(expectedExceptions = UnsupportedOperationException.class) 79 | public void writeWithNull() throws IOException { 80 | 81 | BlobChannel blobChannel = new BlobChannel(getWritableByteChannel()); 82 | ByteBuffer byteBuffer = ByteBuffer.allocate(30); 83 | blobChannel.write(byteBuffer); 84 | } 85 | 86 | private ReadableByteChannel getReadableByteChannel() { 87 | 88 | return null; 89 | } 90 | 91 | private WritableByteChannel getWritableByteChannel() { 92 | 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ballerina/string_reader.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | 17 | # Represents a reader which will wrap string content as a channel. 18 | public class StringReader { 19 | private ReadableCharacterChannel? charChannel; 20 | 21 | # Constructs a channel to read string. 22 | # 23 | # + content - The content, which should be written 24 | # + encoding - Encoding of the characters of the content 25 | public isolated function init(string content, string encoding = "UTF-8") { 26 | byte[] contentBytes = content.toBytes(); 27 | ReadableByteChannel|Error byteChannel = createReadableChannel(contentBytes); 28 | if byteChannel is Error { 29 | self.charChannel = (); 30 | } else { 31 | self.charChannel = new ReadableCharacterChannel(byteChannel, encoding); 32 | } 33 | } 34 | 35 | # Reads string as JSON using the reader. 36 | # ```ballerina 37 | # io:StringReader reader = new("{\"name\": \"Alice\"}"); 38 | # json|io:Error? person = reader.readJson(); 39 | # ``` 40 | # 41 | # + return - JSON or else an `io:Error` if any error occurred 42 | public isolated function readJson() returns json|Error { 43 | if self.charChannel is ReadableCharacterChannel { 44 | var result = self.charChannel; 45 | return result.readJson(); 46 | } 47 | return; 48 | } 49 | 50 | # Reads a string as XML using the reader. 51 | # ```ballerina 52 | # io:StringReader reader = new("Alice"); 53 | # xml|io:Error? person = reader.readXml(); 54 | # ``` 55 | # 56 | # + return - XML or else an `io:Error` if any error occurred 57 | public isolated function readXml() returns xml|Error? { 58 | if self.charChannel is ReadableCharacterChannel { 59 | var result = self.charChannel; 60 | return result.readXml(); 61 | } 62 | return; 63 | } 64 | 65 | # Reads the characters from the given string. 66 | # ```ballerina 67 | # io:StringReader reader = new("Some text"); 68 | # string|io:Error? person = reader.readChar(4); 69 | # ``` 70 | # 71 | # + nCharacters - Number of characters to be read 72 | # + return - String or else an `io:Error` if any error occurred 73 | public isolated function readChar(int nCharacters) returns string|Error? { 74 | if self.charChannel is ReadableCharacterChannel { 75 | var result = self.charChannel; 76 | return result.read(nCharacters); 77 | } 78 | return; 79 | } 80 | 81 | # Closes the string reader. 82 | # ```ballerina 83 | # io:Error? err = reader.close(); 84 | # ``` 85 | # 86 | # + return - `()` or else an `io:Error` if any error occurred 87 | public isolated function close() returns Error? { 88 | if self.charChannel is ReadableCharacterChannel { 89 | var result = self.charChannel; 90 | return result.close(); 91 | } 92 | return; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ballerina/readable_record_channel.bal: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 2 | // 3 | // WSO2 Inc. licenses this file to you under the Apache License, 4 | // Version 2.0 (the "License"); you may not use this file except 5 | // in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, 11 | // software distributed under the License is distributed on an 12 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | // KIND, either express or implied. See the License for the 14 | // specific language governing permissions and limitations 15 | // under the License. 16 | import ballerina/jballerina.java; 17 | 18 | # Represents a readable record channel. 19 | public class ReadableTextRecordChannel { 20 | 21 | private ReadableCharacterChannel charChannel; 22 | private string rs; 23 | private string fs; 24 | 25 | # Initializes a readable text record channel. 26 | # 27 | # + charChannel - The `io:ReadableCharacterChannel` which will point to the input/output resource 28 | # + fs - The field separator (this could be a regex) 29 | # + rs - The record separator (this could be a regex) 30 | public isolated function init(ReadableCharacterChannel charChannel, string fs = "", string rs = "", 31 | string fmt = "default") { 32 | self.charChannel = charChannel; 33 | self.rs = rs; 34 | self.fs = fs; 35 | initReadableTextRecordChannel(self, charChannel, fs, rs, fmt); 36 | } 37 | 38 | # Checks whether there is a record left to be read. 39 | # ```ballerina 40 | # boolean hasNext = readableRecChannel.hasNext(); 41 | # ``` 42 | # 43 | # + return - True if there is a record left to be read 44 | public isolated function hasNext() returns boolean { 45 | return hasNextExtern(self); 46 | } 47 | 48 | # Reads the next record from the input/output resource. 49 | # ```ballerina 50 | # string[]|io:Error record = readableRecChannel.getNext(); 51 | # ``` 52 | # 53 | # + return - Set of fields included in the record or else `io:Error` 54 | public isolated function getNext() returns string[]|Error { 55 | return getNextExtern(self); 56 | } 57 | 58 | # Closes the record channel. 59 | # After a channel is closed, any further reading operations will cause an error. 60 | # ```ballerina 61 | # io:Error err = readableRecChannel.close(); 62 | # ``` 63 | # 64 | # + return - `()` or else an `io:Error` if any error occurred 65 | public isolated function close() returns Error? { 66 | return closeReadableTextRecordChannelExtern(self); 67 | } 68 | } 69 | 70 | isolated function initReadableTextRecordChannel(ReadableTextRecordChannel textChannel, 71 | ReadableCharacterChannel charChannel, string fs, string rs, string fmt) = @java:Method { 72 | name: "initRecordChannel", 73 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 74 | } external; 75 | 76 | isolated function hasNextExtern(ReadableTextRecordChannel textChannel) returns boolean = @java:Method { 77 | name: "hasNext", 78 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 79 | } external; 80 | 81 | isolated function getNextExtern(ReadableTextRecordChannel textChannel) returns string[]|Error = @java:Method { 82 | name: "getNext", 83 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 84 | } external; 85 | 86 | isolated function closeReadableTextRecordChannelExtern(ReadableTextRecordChannel textChannel) returns Error? = @java:Method { 87 | name: "close", 88 | 'class: "io.ballerina.stdlib.io.nativeimpl.RecordChannelUtils" 89 | } external; 90 | --------------------------------------------------------------------------------