├── .all-contributorsrc ├── .devcontainer.json ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── karatewindows-matcher.json ├── releasecheck.java └── workflows │ ├── ci-build.yml │ ├── codeql-analysis.yml │ ├── install-tests.yml │ ├── publish-packages.yml │ ├── report.yml │ └── tag-and-release.yml ├── .gitignore ├── .gitpod.yml ├── .justfile ├── .sdkmanrc ├── CONTRIBUTING.adoc ├── CONTRIBUTORS.md ├── LICENSE ├── RELEASE.md ├── bisect.sh ├── bootstrap.sh ├── build.gradle ├── codecov.yml ├── devfile.yaml ├── docs ├── antora.yml ├── genadoc.java └── modules │ ├── ROOT │ ├── images │ │ └── jbang_logo.svg │ ├── nav.adoc │ └── pages │ │ ├── alias_catalogs.adoc │ │ ├── caching.adoc │ │ ├── configuration.adoc │ │ ├── debugging.adoc │ │ ├── dependencies.adoc │ │ ├── editing.adoc │ │ ├── exporting.adoc │ │ ├── faq.adoc │ │ ├── index.adoc │ │ ├── install.adoc │ │ ├── installation.adoc │ │ ├── integration.adoc │ │ ├── javaversions.adoc │ │ ├── organizing.adoc │ │ ├── running.adoc │ │ ├── templates.adoc │ │ └── usage.adoc │ └── cli │ ├── nav.adoc │ ├── pages │ ├── jbang-alias-add.adoc │ ├── jbang-alias-list.adoc │ ├── jbang-alias-remove.adoc │ ├── jbang-alias.adoc │ ├── jbang-app-install.adoc │ ├── jbang-app-list.adoc │ ├── jbang-app-setup.adoc │ ├── jbang-app-uninstall.adoc │ ├── jbang-app.adoc │ ├── jbang-build.adoc │ ├── jbang-cache-clear.adoc │ ├── jbang-cache.adoc │ ├── jbang-catalog-add.adoc │ ├── jbang-catalog-list.adoc │ ├── jbang-catalog-remove.adoc │ ├── jbang-catalog-update.adoc │ ├── jbang-catalog.adoc │ ├── jbang-completion.adoc │ ├── jbang-config-get.adoc │ ├── jbang-config-list.adoc │ ├── jbang-config-set.adoc │ ├── jbang-config-unset.adoc │ ├── jbang-config.adoc │ ├── jbang-edit.adoc │ ├── jbang-export-fatjar.adoc │ ├── jbang-export-gradle.adoc │ ├── jbang-export-jlink.adoc │ ├── jbang-export-local.adoc │ ├── jbang-export-maven.adoc │ ├── jbang-export-mavenrepo.adoc │ ├── jbang-export-native.adoc │ ├── jbang-export-portable.adoc │ ├── jbang-export.adoc │ ├── jbang-info-classpath.adoc │ ├── jbang-info-jar.adoc │ ├── jbang-info-tools.adoc │ ├── jbang-info.adoc │ ├── jbang-init.adoc │ ├── jbang-jdk-default.adoc │ ├── jbang-jdk-home.adoc │ ├── jbang-jdk-install.adoc │ ├── jbang-jdk-java-env.adoc │ ├── jbang-jdk-list.adoc │ ├── jbang-jdk-uninstall.adoc │ ├── jbang-jdk.adoc │ ├── jbang-run.adoc │ ├── jbang-template-add.adoc │ ├── jbang-template-list.adoc │ ├── jbang-template-remove.adoc │ ├── jbang-template.adoc │ ├── jbang-trust-add.adoc │ ├── jbang-trust-list.adoc │ ├── jbang-trust-remove.adoc │ ├── jbang-trust.adoc │ ├── jbang-version.adoc │ ├── jbang-wrapper-install.adoc │ ├── jbang-wrapper.adoc │ └── jbang.adoc │ └── partials │ └── nav-jbang.adoc ├── examples ├── .gitignore └── readme.adoc ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── jbang_icon.png ├── jbang_icon.svg ├── jbang_logo.png └── jbang_logo.svg ├── itests ├── JULAgent.java ├── JULTest.java ├── RootOne.java ├── SankeyPlotTest.java ├── SankeyPlotTestWithDeps.java ├── Two.java ├── alltags.java ├── aserta ├── bar │ └── Bar.java ├── basic.jsh ├── brokenresource.java ├── build.jbang ├── classpath_example.java ├── classpath_log.groovy ├── classpath_log.java ├── classpath_log.kt ├── classpath_log_bom.java ├── classpath_log_grab.java ├── classpath_log_grab_with_ranges.java ├── classpath_main.kt ├── deps.jsh ├── dualclass.java ├── ec.jsh ├── echo.bat ├── echo.java ├── echo.ps1 ├── exporttags.java ├── foo.java ├── funcs.jsh ├── gh_fetch_release_assets.java ├── gh_release_stats.java ├── hello.jsh ├── hellojar.jar ├── hellojsh ├── helloworld.groovy ├── helloworld.java ├── helloworld.jsh ├── helloworld.kt ├── java4321.java ├── jbang-catalog.json ├── keyvalue.java ├── kubectl-example ├── logback.xml ├── main.jsh ├── nakedmain │ ├── classinstance.java │ ├── noclass.java │ └── noclasswithargs.java ├── nested │ ├── NestedOne.java │ └── NestedTwo.java ├── noints.java ├── one.java ├── onedep.java ├── othernested │ └── OtherThree.java ├── quote.java ├── quote_notags.java ├── readme.adoc ├── readme.md ├── res │ ├── resource.java │ ├── resource.properties │ ├── sub │ │ └── sub.properties │ └── test.properties ├── resource.java ├── resource.properties ├── resources.java ├── resourcesmnt.java ├── runkotlin.kt ├── selfdep.java ├── sources.java ├── sources │ ├── yang.java │ └── ying.java ├── templates │ └── test.java.qute ├── test.bat ├── test.java ├── test_suite.sh └── with space │ └── helloworld.java ├── jreleaser.yml ├── misc ├── bootstrap_jbang.sh ├── demos │ ├── basic-jbang.sh │ ├── demo-magic.sh │ └── readme.adoc ├── eclipse_formatting_nowrap.xml ├── promotesnap.sh ├── proxy │ ├── README.md │ ├── config │ │ ├── settings.xml │ │ └── tinyproxy.conf │ └── docker-compose.yml ├── updatesnap.sh └── updatespec.sh ├── pipelines.puml ├── readme.adoc ├── renovate.json ├── settings.gradle └── src ├── it ├── java │ └── dev │ │ └── jbang │ │ └── it │ │ ├── AliasIT.java │ │ ├── AppIT.java │ │ ├── BaseIT.java │ │ ├── CacheIT.java │ │ ├── CatalogIT.java │ │ ├── CommandResult.java │ │ ├── CommandResultAssert.java │ │ ├── ConfigIT.java │ │ ├── DependenciesIT.java │ │ ├── DeprecatedIT.java │ │ ├── EditIT.java │ │ ├── ExportIT.java │ │ ├── InitIT.java │ │ ├── JarIT.java │ │ ├── JavaVersionIT.java │ │ ├── JshIT.java │ │ ├── MarkdownIT.java │ │ ├── QuotingIT.java │ │ ├── QuotingWinIT.java │ │ ├── RunIT.java │ │ ├── RunKotlin.java │ │ ├── RunNix.java │ │ ├── ShellEnvIT.java │ │ ├── TemplateIT.java │ │ ├── VersionIT.java │ │ └── WrapperIT.java └── resources │ └── allure.properties ├── jreleaser ├── distributions │ └── jbang │ │ ├── brew │ │ ├── README.md.tpl │ │ └── formula.rb.tpl │ │ ├── docker │ │ ├── Dockerfile.tpl │ │ ├── README.md.tpl │ │ ├── action.yml.tpl │ │ ├── container-structure-test.yaml │ │ └── entrypoint │ │ └── snap │ │ ├── .gitignore │ │ ├── README.md.tpl │ │ └── snap │ │ └── snapcraft.yaml.tpl └── templates │ └── article │ └── blogpost.adoc ├── main ├── assembly │ └── assembly.xml ├── java │ └── dev │ │ └── jbang │ │ ├── Cache.java │ │ ├── Configuration.java │ │ ├── Main.java │ │ ├── Settings.java │ │ ├── catalog │ │ ├── Alias.java │ │ ├── Catalog.java │ │ ├── CatalogItem.java │ │ ├── CatalogRef.java │ │ ├── CatalogUtil.java │ │ ├── ImplicitCatalogRef.java │ │ ├── Template.java │ │ └── TemplateProperty.java │ │ ├── cli │ │ ├── Alias.java │ │ ├── App.java │ │ ├── BaseBuildCommand.java │ │ ├── BaseCommand.java │ │ ├── Build.java │ │ ├── BuildMixin.java │ │ ├── Cache.java │ │ ├── Catalog.java │ │ ├── CommaSeparatedConverter.java │ │ ├── Completion.java │ │ ├── Config.java │ │ ├── DependencyInfoMixin.java │ │ ├── DeprecatedMessageHandler.java │ │ ├── Edit.java │ │ ├── ExitException.java │ │ ├── Export.java │ │ ├── ExportMixin.java │ │ ├── FormatMixin.java │ │ ├── Info.java │ │ ├── Init.java │ │ ├── JBang.java │ │ ├── Jdk.java │ │ ├── JdkProvidersMixin.java │ │ ├── KeyValueConsumer.java │ │ ├── NativeMixin.java │ │ ├── ResourceNotFoundException.java │ │ ├── Run.java │ │ ├── RunMixin.java │ │ ├── ScriptMixin.java │ │ ├── StrictParameterPreprocessor.java │ │ ├── Template.java │ │ ├── TemplatePropertyConverter.java │ │ ├── Trust.java │ │ ├── Version.java │ │ ├── VersionProvider.java │ │ └── Wrapper.java │ │ ├── dependencies │ │ ├── ArtifactInfo.java │ │ ├── ArtifactResolver.java │ │ ├── DependencyCache.java │ │ ├── DependencyException.java │ │ ├── DependencyResolver.java │ │ ├── DependencyUtil.java │ │ ├── Detector.java │ │ ├── JitPackUtil.java │ │ ├── MavenCoordinate.java │ │ ├── MavenRepo.java │ │ └── ModularClassPath.java │ │ ├── net │ │ ├── EditorManager.java │ │ ├── GroovyManager.java │ │ ├── KotlinManager.java │ │ └── TrustedSources.java │ │ ├── source │ │ ├── AppBuilder.java │ │ ├── BuildContext.java │ │ ├── Builder.java │ │ ├── CmdGenerator.java │ │ ├── CmdGeneratorBuilder.java │ │ ├── CodeBuilderProvider.java │ │ ├── DirectResourceRef.java │ │ ├── KeyValue.java │ │ ├── LazyResourceRef.java │ │ ├── Project.java │ │ ├── ProjectBuilder.java │ │ ├── RefTarget.java │ │ ├── ResourceRef.java │ │ ├── ResourceResolver.java │ │ ├── Source.java │ │ ├── SourceSet.java │ │ ├── TagReader.java │ │ ├── buildsteps │ │ │ ├── CompileBuildStep.java │ │ │ ├── IntegrationBuildStep.java │ │ │ ├── JarBuildStep.java │ │ │ └── NativeBuildStep.java │ │ ├── generators │ │ │ ├── BaseCmdGenerator.java │ │ │ ├── JarCmdGenerator.java │ │ │ ├── JshCmdGenerator.java │ │ │ └── NativeCmdGenerator.java │ │ ├── resolvers │ │ │ ├── AliasResourceResolver.java │ │ │ ├── ClasspathResourceResolver.java │ │ │ ├── CombinedResourceResolver.java │ │ │ ├── FileResourceResolver.java │ │ │ ├── GavResourceResolver.java │ │ │ ├── LazyResourceResolver.java │ │ │ ├── LiteralScriptResourceResolver.java │ │ │ ├── RemoteResourceResolver.java │ │ │ ├── RenamingScriptResourceResolver.java │ │ │ └── SiblingResourceResolver.java │ │ └── sources │ │ │ ├── GroovySource.java │ │ │ ├── JavaSource.java │ │ │ ├── JshSource.java │ │ │ ├── KotlinSource.java │ │ │ └── MarkdownSource.java │ │ ├── spi │ │ ├── IntegrationInput.java │ │ ├── IntegrationManager.java │ │ └── IntegrationResult.java │ │ └── util │ │ ├── CommandBuffer.java │ │ ├── ConfigUtil.java │ │ ├── ConsoleInput.java │ │ ├── ConsoleInputReadTask.java │ │ ├── ConsoleOutput.java │ │ ├── FileTypeAdapter.java │ │ ├── JBangFormatter.java │ │ ├── JarUtil.java │ │ ├── JavaUtil.java │ │ ├── ModuleUtil.java │ │ ├── PathTypeAdapter.java │ │ ├── PropertiesValueResolver.java │ │ ├── TemplateEngine.java │ │ ├── UnpackUtil.java │ │ ├── Util.java │ │ └── VersionChecker.java ├── java9 │ └── dev │ │ └── jbang │ │ └── util │ │ └── ModuleUtil9.java ├── resources │ ├── .qute.classpath │ ├── .qute.project │ ├── README.qute.md │ ├── build.qute.gradle │ ├── dist │ │ ├── gradle │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ ├── gradle-wrapper-jar │ │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── update-version.sh │ │ └── maven │ │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ └── maven-wrapper.properties │ │ │ ├── mvnw │ │ │ ├── mvnw.cmd │ │ │ └── update-version.sh │ ├── export-build.qute.gradle │ ├── export-pom.qute.xml │ ├── idea-port-4004.qute.xml │ ├── idea.qute.xml │ ├── init-agent.java.qute │ ├── init-cli.java.qute │ ├── init-hello.groovy.qute │ ├── init-hello.java.qute │ ├── init-hello.kt.qute │ ├── init-qcli.java.qute │ ├── init-qmetrics.java.qute │ ├── init-qrest.java.qute │ ├── init-readme.md.qute │ ├── initClass.java.qute │ ├── jbang-catalog.json │ ├── jbang.properties │ ├── jbang_icon_64x64.png │ ├── launch.qute.json │ ├── logging.properties │ ├── main-port-4004.qute.launch │ ├── main.qute.launch │ ├── module-info.qute.java │ ├── pom.qute.xml │ ├── settings.qute.json │ └── trusted-sources.json.qute └── scripts │ ├── choco │ ├── jbang.nuspec │ └── tools │ │ ├── LICENSE.txt │ │ ├── VERIFICATION.txt │ │ ├── chocolateyinstall.ps1 │ │ └── chocolateyuninstall.ps1 │ ├── jbang │ ├── jbang.cmd │ ├── jbang.ps1 │ ├── spec │ └── jbang.spec │ └── test.cmd └── test ├── java └── dev │ └── jbang │ ├── BaseTest.java │ ├── JBangHandler.java │ ├── TestConfiguration.java │ ├── TestImplicitAlias.java │ ├── cli │ ├── TemplatePropertyConverterTest.java │ ├── TestAlias.java │ ├── TestAliasNearest.java │ ├── TestAliasNearestWithBaseRef.java │ ├── TestAliasWithBaseRef.java │ ├── TestApp.java │ ├── TestArguments.java │ ├── TestCatalog.java │ ├── TestCatalogNearest.java │ ├── TestConfig.java │ ├── TestEdit.java │ ├── TestEditLocate.java │ ├── TestEditWithPackage.java │ ├── TestEditWithPom.java │ ├── TestExport.java │ ├── TestExternalDeps.java │ ├── TestInfo.java │ ├── TestInit.java │ ├── TestJdk.java │ ├── TestRun.java │ ├── TestSettings.java │ └── TestTemplate.java │ ├── dependencies │ ├── DependencyResolverTest.java │ ├── TestArtifactInfo.java │ ├── TestGrape.java │ └── TestJitPack.java │ ├── net │ ├── TestJdkManager.java │ ├── TestTrustEdit.java │ └── TestTrustedSources.java │ ├── source │ ├── TestBuilder.java │ ├── TestMain.java │ ├── TestModule.java │ ├── TestProject.java │ ├── TestProjectBuilder.java │ ├── TestSameSourceInDifferentPaths.java │ ├── TestSource.java │ ├── TestSourcesMultipleSomeMissingFiles.java │ ├── TestSourcesMutualDependency.java │ ├── TestSourcesRecursivelyMultipleFiles.java │ └── TestTagReader.java │ └── util │ ├── NoOpUrlConnection.java │ ├── TestCommandBuffer.java │ ├── TestTrustedSources.java │ ├── TestUtil.java │ └── TestUtilDownloads.java └── resources ├── allure.properties └── junit-platform.properties /.devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "postCreateCommand": "curl -Ls https://sh.jbang.dev | bash -s - app setup", 3 | "extensions": ["vscjava.vscode-java-pack"] 4 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows understands lf thus lets just force it 2 | * text eol=lf 3 | 4 | # Denote all files that are truly binary and should not be modified. 5 | *.png binary 6 | *.jpg binary 7 | *.jar binary 8 | *.db binary 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **JBang version** 24 | Paste output of `jbang version --verbose` 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Question/Discussion 3 | url: https://github.com/jbangdev/jbang/discussions/new 4 | about: I have a question or topic to discuss which is not a bug nor new feature. 5 | - name: JBang Gitter Chat 6 | url: https://gitter.im/jbangdev/community 7 | about: If you prefer live chat with the developers, we hang out on Gitter. 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: ideas 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 15 | -------------------------------------------------------------------------------- /.github/karatewindows-matcher.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "karate-windows", 5 | "pattern": [ 6 | { 7 | "regexp": "^The system cannot find the path specified.*", 8 | "message": 0 9 | } 10 | ] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.github/workflows/install-tests.yml: -------------------------------------------------------------------------------- 1 | name: install-tests 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | macos: 7 | runs-on: macos-latest 8 | steps: 9 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 10 | - name: Remove Java 11 | run: | 12 | sudo rm -rf /Library/Java/* 13 | sudo rm -rf /Users/runner/hostedtoolcache/Java* 14 | - name: check jbang does not exist 15 | run: | 16 | if command -v jbang; then 17 | echo "jbang already exists!" 18 | exit 1 19 | fi 20 | - name: install jbang 21 | run: | 22 | curl -Ls https://sh.jbang.dev | bash -s - app setup 23 | source ~/.zshrc 24 | if ! command -v jbang; then 25 | echo "jbang not found after install!" 26 | exit 1 27 | fi 28 | - name: run jbang no java 29 | run: | 30 | source ~/.zshrc 31 | jbang init -t cli testcli.java 32 | ./testcli.java 33 | - name: run jbang java 17 34 | run: | 35 | jbang init -t cli testcli.java 36 | jbang --java 17 testcli.java 37 | -------------------------------------------------------------------------------- /.github/workflows/report.yml: -------------------------------------------------------------------------------- 1 | ## have to upload via this seperate workflow 2 | ## to avoid limitations of PR's from forked 3 | ## repos which wont have write access by default. 4 | 5 | name: report 6 | on: 7 | workflow_run: 8 | workflows: [ci-build] 9 | types: [completed] 10 | 11 | permissions: 12 | checks: write 13 | pull-requests: write 14 | 15 | jobs: 16 | checks: 17 | runs-on: ubuntu-latest 18 | steps: 19 | #- name: Set up GitHub CLI 20 | # uses: actions/setup-gh@v2 21 | 22 | - name: Get workflow run details 23 | id: workflow_details 24 | env: 25 | GH_TOKEN: ${{ github.token }} 26 | run: | 27 | gh api repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} \ 28 | --jq '.head_branch' > branch.txt 29 | BRANCH_NAME=$(cat branch.txt) 30 | echo "branch_name=${BRANCH_NAME}" >> $GITHUB_ENV 31 | 32 | - name: Fetch PR number 33 | id: fetch_pr 34 | env: 35 | GH_TOKEN: ${{ github.token }} 36 | run: | 37 | PR=$(gh pr list --head "${{ env.branch_name }}" --json number --jq '.[0].number') 38 | echo "pr_number=${PR}" >> $GITHUB_ENV 39 | 40 | - name: Output PR number 41 | run: | 42 | echo "The PR number is: ${{ env.pr_number }}" 43 | 44 | - name: Download Test Report 45 | uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 46 | with: 47 | name: junit-test-results-* 48 | #path: test-${{ matrix.os }} 49 | #pattern: my-artifact-* 50 | merge-multiple: true 51 | run-id: ${{ github.event.workflow_run.id }} 52 | - name: Publish Test Report 53 | uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 # v5 54 | with: 55 | commit: ${{github.event.workflow_run.head_sha}} 56 | report_paths: '**/build/test-results/test/TEST-*.xml' 57 | comment: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .vscode 4 | .settings 5 | target 6 | .idea 7 | *.iml 8 | /build 9 | .gradle 10 | .factorypath 11 | bin 12 | homebrew-tap 13 | RESULTS 14 | *.db 15 | jbang-action 16 | out 17 | node_modules 18 | package-lock.json 19 | *.jfr 20 | itests/hello.java 21 | *.class 22 | CHANGELOG.md 23 | allure-report 24 | allure-results 25 | .allure 26 | .DS_Store 27 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - before: curl -Ls https://sh.jbang.dev | bash -s - app setup 3 | - init: ./gradlew build 4 | 5 | -------------------------------------------------------------------------------- /.justfile: -------------------------------------------------------------------------------- 1 | open := if os() == "macos" { "open" } else if os() == "windows" { "start" } else { "xdg-open" } 2 | 3 | #@default: 4 | # just --choose 5 | 6 | # build without tests 7 | build: 8 | ./gradlew spotlessApply installDist -x test 9 | 10 | format: 11 | ./gradlew spotlessApply 12 | 13 | # run tests 14 | test: 15 | ./gradlew test 16 | 17 | preitest := if path_exists('build/install/jbang/bin') != 'true' { 18 | './gradlew spotlessApply installDist -x test' 19 | } else { 20 | '' 21 | } 22 | 23 | # open test report 24 | opentest: 25 | {{open}} build/reports/tests/test/index.html 26 | 27 | # run integration tests 28 | itest: 29 | {{preitest}} 30 | ./gradlew integrationTest 31 | 32 | # open shell with latest build in path 33 | jbang *args: 34 | PATH="build/install/jbang/bin:$PATH" jbang {{args}} 35 | 36 | # open integeration test report 37 | openitest: 38 | {{open}} build/reports/allure-report/allureReport/index.html 39 | 40 | # tag minor 41 | tagminor: 42 | git commit --allow-empty -m "[minor] release" 43 | ./gradlew tag 44 | 45 | tagpatch: 46 | git commit --allow-empty -m "[patch] release" 47 | ./gradlew tag 48 | 49 | itestreport: # todo: should not be needed to clean 50 | -./gradlew integrationTest 51 | ./gradlew allureReport --clean 52 | -------------------------------------------------------------------------------- /.sdkmanrc: -------------------------------------------------------------------------------- 1 | # Enable auto-env through the sdkman_auto_env config 2 | # Add key=value pairs of SDKs to use below 3 | 4 | # Java 5 | java=11.0.26-tem 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Max Rydahl Andersen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # How JBang is released 2 | 3 | Short overview on how JBang is built/released. 4 | 5 | ```mermaid 6 | graph TD 7 | tag[Tag repo] -->|build and testing| jreleaser{jreleaser} 8 | jreleaser -->|prepare release draft| draft[release draft] 9 | draft -->humanrelease[human release on github] 10 | humanrelease --> publishpackages[publish packages] 11 | publishpackages -->|build and testing| publish{jreleaser publish} 12 | publish --> brew[https://github.com/jbangdev/homebrew-tap] 13 | publish --> chocolatey 14 | publish --> docker[https://github.com/jbangdev/jbang-action] 15 | publish --> |scoop| scoop[https://github.com/jbangdev/scoop-bucket] 16 | publish --> sdkman 17 | publish --> snap[https://github.com/jbangdev/jbang-snap] 18 | publish --> announce 19 | announce --> sdkmanpublish 20 | announce --> jbangtwitter 21 | snap -->|webhook| snaprepo[https://snapcraft.io/jbang/builds] 22 | docker --> |publish| dockerhub 23 | docker --> |publish| quay 24 | docker --> |publish| github 25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /bisect.sh: -------------------------------------------------------------------------------- 1 | ## adjust the test.java and this script to use in bisect to 2 | ## find when something stopped/started working. 3 | ## git co knownbadcommit 4 | ## git bisect start 5 | ## git bisect bad 6 | ## git co knowngoodcommit 7 | ## git bisect run ./bisect.sh 8 | ## git bisect reset 9 | ## 10 | ## see details at https://stackoverflow.com/a/22592593/71208 11 | ./gradlew clean build installDist -x test 12 | export PATH=/Users/max/code/personal/jbangdev/jbang/build/install/jbang/bin:$PATH 13 | rm -f mode.quarkus 14 | jbang --fresh -Dquarkus.dev test.java 15 | grep DEVELOPMENT mode.quarkus 16 | 17 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | ## This script is an experiment to bootstrap jbang with jbang itself. 2 | 3 | ## in gradle we have plugin to generate BuildConfig with version info in it. 4 | ## For now just generate a placeholder. Ultimately could be some other script to generate the file. 5 | mkdir -p generated 6 | cat << EOF > generated/BuildConfig.java 7 | package dev.jbang; 8 | 9 | public final class BuildConfig { 10 | public static final String VERSION = "999-jbang"; 11 | public static final String NAME = "jbang"; 12 | 13 | private BuildConfig() { 14 | } 15 | } 16 | EOF 17 | 18 | jbang export local --verbose --force -O jbang.jar --sources 'src/main/java,generated/' --files 'src/main/resources' --repos mavencentral,jitpack --deps org.jboss:jandex:2.2.3.Final,org.slf4j:slf4j-nop:1.7.30,com.offbytwo:docopt:0.6.0.20150202,org.apache.commons:commons-text:1.10.0,org.apache.commons:commons-compress:1.20,info.picocli:picocli:4.6.3,io.quarkus.qute:qute-core:1.12.2.Final,kr.motd.maven:os-maven-plugin:1.7.0,org.codehaus.plexus:plexus-java:1.0.6,com.google.code.gson:gson:2.9.0,org.jsoup:jsoup:1.13.1,org.codejive:java-properties:0.0.4,com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-api:3.1.5-allowpom,com.github.jbangdev.jbang-resolver:shrinkwrap-resolver-impl-maven:3.1.5-allowpom src/main/java/dev/jbang/Main.java 19 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | informational: true 6 | -------------------------------------------------------------------------------- /devfile.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: 1.0.0 3 | metadata: 4 | name: jbang 5 | components: 6 | - 7 | type: chePlugin 8 | id: redhat/java/latest 9 | - 10 | type: dockerimage 11 | alias: gradle 12 | image: quay.io/eclipse/che-java11-gradle:nightly 13 | env: 14 | - name: GRADLE_USER_HOME 15 | value: /home/gradle/.gradle 16 | - name: JAVA_OPTS 17 | value: "-XX:MaxRAMPercentage=50 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 18 | -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 19 | -Dsun.zip.disableMemoryMapping=true -Xms20m -Djava.security.egd=file:/dev/./urandom" 20 | - name: JAVA_TOOL_OPTIONS 21 | value: "-XX:MaxRAMPercentage=50 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 22 | -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 23 | -Dsun.zip.disableMemoryMapping=true -Xms20m -Djava.security.egd=file:/dev/./urandom" 24 | - name: HOME 25 | value: /home/gradle 26 | memoryLimit: 512Mi 27 | volumes: 28 | - name: gradle 29 | containerPath: /home/gradle/.gradle 30 | mountSources: true 31 | commands: 32 | - 33 | name: build 34 | actions: 35 | - 36 | type: exec 37 | component: gradle 38 | command: "./gradlew" 39 | workdir: ${CHE_PROJECTS_ROOT}/jbang 40 | 41 | -------------------------------------------------------------------------------- /docs/antora.yml: -------------------------------------------------------------------------------- 1 | name: guide 2 | title: JBang 3 | version: latest 4 | nav: 5 | - modules/ROOT/nav.adoc 6 | - modules/cli/nav.adoc 7 | - modules/jbang-idea/nav.adoc -------------------------------------------------------------------------------- /docs/modules/ROOT/nav.adoc: -------------------------------------------------------------------------------- 1 | * xref:index.adoc[] 2 | * xref:installation.adoc[] 3 | * xref:usage.adoc[] 4 | * xref:dependencies.adoc[] 5 | * xref:javaversions.adoc[] 6 | * xref:organizing.adoc[] 7 | * xref:running.adoc[] 8 | * xref:debugging.adoc[] 9 | * xref:editing.adoc[] 10 | * xref:exporting.adoc[] 11 | * xref:install.adoc[] 12 | * xref:templates.adoc[] 13 | * xref:alias_catalogs.adoc[] 14 | * xref:integration.adoc[] 15 | * xref:configuration.adoc[] 16 | * xref:caching.adoc[] 17 | * xref:faq.adoc[] -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/caching.adoc: -------------------------------------------------------------------------------- 1 | = Caching 2 | :idprefix: 3 | :idseparator: - 4 | ifndef::env-github[] 5 | :icons: font 6 | endif::[] 7 | ifdef::env-github[] 8 | :caution-caption: :fire: 9 | :important-caption: :exclamation: 10 | :note-caption: :paperclip: 11 | :tip-caption: :bulb: 12 | :warning-caption: :warning: 13 | endif::[] 14 | 15 | In previous versions of `jbang`, Java 10+ direct launch of `.java` was used, but since v0.6 `jbang` works with Java 8 and thus it needs to do a separate compile step. Besides now working with Java 8 this also allows to cache the compiled script and thus launch faster on consecutive runs. 16 | 17 | The caching goes to `~/.jbang/cache` by default, you can run `jbang cache clear` to remove all cache data from this folder. 18 | 19 | The default cache location can be overwritten by the environment variable `JBANG_CACHE_DIR`. If `JBANG_DIR` environment variable is set, the `cache` folder will be placed there. -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/debugging.adoc: -------------------------------------------------------------------------------- 1 | = Debugging 2 | :idprefix: 3 | :idseparator: - 4 | ifndef::env-github[] 5 | :icons: font 6 | endif::[] 7 | ifdef::env-github[] 8 | :caution-caption: :fire: 9 | :important-caption: :exclamation: 10 | :note-caption: :paperclip: 11 | :tip-caption: :bulb: 12 | :warning-caption: :warning: 13 | endif::[] 14 | 15 | When running `.java` scripts with `jbang` you can pass the `--debug`-flag and the script will enable debug, 16 | suspend the execution and wait until you connect a debugger to port 4004. 17 | 18 | [source, bash] 19 | ---- 20 | jbang --debug helloworld.java 21 | Listening for transport dt_socket at address: 4004 22 | ---- 23 | 24 | You can change the debug port and host by passing in a interface pattern and number to the debug argument, e.g., `--debug=*:4321`. 25 | 26 | This will make it use port 4321 and make it listen on all ('*') network interfaces. 27 | 28 | NOTE: Be sure to put a breakpoint in your IDE/debugger before you connect to make the debugger actually stop when you need it. 29 | 30 | Additionally you can pass in a additional key/value options to the debug string, e.g., `--debug=server=n,suspend=y`. To have the debugger 31 | connect to the IDE and suspend the execution when it connects as opposed to having the IDE connect. 32 | 33 | You can see the key/value options supported in OpenJDK JPDA https://docs.oracle.com/en/java/javase/11/docs/specs/jpda/conninv.html[documentation]. 34 | 35 | == Debug info 36 | 37 | JBang since version 0.100 compiles with debug info enabled by default. You can use `-C=-g` to tweak how much debug info is included: `jbang -C=-g=lines,vars,source` or to turn it off use `jbang -C=-g=none". 38 | 39 | == Debug jbang itself 40 | 41 | Java itself will add `JAVA_TOOL_OPTIONS` which will apply to `jbang` too. 42 | 43 | For finer and more explicit control the scripts, `jbang` will add `JBANG_JAVA_OPTIONS` to the call to `jbang` itself. 44 | Thus if you want to enable debug or other details for `jbang` set that environment variable. 45 | 46 | Example that will enable debug on port 1044 and wait/suspend for debugger to connect: 47 | 48 | [source,bash] 49 | ---- 50 | JBANG_JAVA_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044 jbang env@jbangdev 51 | ---- -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/install.adoc: -------------------------------------------------------------------------------- 1 | = Install Apps 2 | :idprefix: 3 | :idseparator: - 4 | ifndef::env-github[] 5 | :icons: font 6 | endif::[] 7 | ifdef::env-github[] 8 | :caution-caption: :fire: 9 | :important-caption: :exclamation: 10 | :note-caption: :paperclip: 11 | :tip-caption: :bulb: 12 | :warning-caption: :warning: 13 | endif::[] 14 | 15 | Since version 0.56 jbang comes with ability to setup jbang to put scripts/apps into your `PATH` 16 | using `jbang app`. This is useful to easily make scripts available from anywhere on any Operating System; 17 | 18 | To get started run `jbang app setup` this will on Windows modify your system wide `PATH` to include a folder managed by jbang. 19 | On bash/zsh based shells it will setup `PATH` in your `bashrc` or `zshrc` file(s.) 20 | 21 | Once setup, you can use `jbang app install ` to install that script into the jbang managed path. 22 | 23 | i.e. `jbang app install myscript.java` will add `myscript` as a command you can run. 24 | 25 | You can also use aliases, like `jbang app install gavsearch@jbangdev`. 26 | 27 | If you have two script/apps with same name or just want to use a specific name you can use `--name` to 28 | control the generated command: `jbang app install --name mvnsearch gavsearch@jbangdev` 29 | 30 | If you want to see which are already installed use `jbang app list` and you can use `jbang app uninstall ` to uninstall 31 | the script/app. 32 | -------------------------------------------------------------------------------- /docs/modules/cli/nav.adoc: -------------------------------------------------------------------------------- 1 | * CLI Reference 2 | + 3 | -- 4 | include::partial$nav-jbang.adoc[] 5 | -- -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-alias.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-alias(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-alias - Manage aliases for scripts. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang alias* *-o* *--fresh* *--quiet* *--verbose* [COMMAND] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Manage aliases for scripts. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | // end::picocli-generated-man-section-arguments[] 52 | 53 | // tag::picocli-generated-man-section-commands[] 54 | == Commands 55 | 56 | xref:jbang-alias-add.adoc[*add*]:: 57 | Add alias for script reference. 58 | 59 | xref:jbang-alias-list.adoc[*list*]:: 60 | Lists locally defined aliases or from the given catalog. 61 | 62 | xref:jbang-alias-remove.adoc[*remove*]:: 63 | Remove existing alias. 64 | 65 | // end::picocli-generated-man-section-commands[] 66 | 67 | // tag::picocli-generated-man-section-exit-status[] 68 | // end::picocli-generated-man-section-exit-status[] 69 | 70 | // tag::picocli-generated-man-section-footer[] 71 | // end::picocli-generated-man-section-footer[] 72 | 73 | // end::picocli-generated-full-manpage[] 74 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-jdk-default.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-jdk-default(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-jdk-default - Sets the default JDK to be used by JBang. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang jdk default* *-o* *--fresh* *--quiet* *--verbose* [_version_] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Sets the default JDK to be used by JBang. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | [_version_]:: 54 | The version of the JDK to select 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-jdk-home.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-jdk-home(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-jdk-home - Prints the folder where the given JDK is installed. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang jdk home* *-o* *--fresh* *--quiet* *--verbose* [_versionOrId_] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Prints the folder where the given JDK is installed. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | [_versionOrId_]:: 54 | The version of the JDK to select 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-jdk-install.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-jdk-install(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-jdk-install - Installs a JDK. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang jdk install* *-o* [*-f*] *--fresh* *--quiet* *--verbose* _versionOrId_ 23 | [_existingJdkPath_] 24 | 25 | // end::picocli-generated-man-section-synopsis[] 26 | 27 | // tag::picocli-generated-man-section-description[] 28 | == Description 29 | 30 | Installs a JDK. 31 | 32 | // end::picocli-generated-man-section-description[] 33 | 34 | // tag::picocli-generated-man-section-options[] 35 | == Options 36 | 37 | *-f*, *--force*:: 38 | Force installation even when already installed 39 | 40 | *--fresh*:: 41 | Make sure we use fresh (i.e. non-cached) resources. 42 | 43 | *-o*, *--offline*:: 44 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 45 | 46 | *--quiet*:: 47 | jbang will be quiet, only print when error occurs. 48 | 49 | *--verbose*:: 50 | jbang will be verbose on what it does. 51 | 52 | // end::picocli-generated-man-section-options[] 53 | 54 | // tag::picocli-generated-man-section-arguments[] 55 | == Arguments 56 | 57 | _versionOrId_:: 58 | The version or id to install 59 | 60 | [_existingJdkPath_]:: 61 | Pre installed JDK path 62 | 63 | // end::picocli-generated-man-section-arguments[] 64 | 65 | // tag::picocli-generated-man-section-commands[] 66 | // end::picocli-generated-man-section-commands[] 67 | 68 | // tag::picocli-generated-man-section-exit-status[] 69 | // end::picocli-generated-man-section-exit-status[] 70 | 71 | // tag::picocli-generated-man-section-footer[] 72 | // end::picocli-generated-man-section-footer[] 73 | 74 | // end::picocli-generated-full-manpage[] 75 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-jdk-java-env.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-jdk-java-env(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-jdk-java-env - Prints out the environment variables needed to use the given JDK. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang jdk java-env* *-o* *--fresh* *--quiet* *--verbose* [_versionOrId_] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Prints out the environment variables needed to use the given JDK. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | [_versionOrId_]:: 54 | The version of the JDK to select 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-jdk-uninstall.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-jdk-uninstall(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-jdk-uninstall - Uninstalls an existing JDK. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang jdk uninstall* *-o* *--fresh* *--quiet* *--verbose* _version_ 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Uninstalls an existing JDK. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | _version_:: 54 | The version to install 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-trust-add.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-trust-add(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-trust-add - Add trust domains. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang trust add* *-o* *--fresh* *--quiet* *--verbose* __... 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Add trust domains. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | __...:: 54 | Rules for trusted sources 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-trust-list.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-trust-list(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-trust-list - Show defined trust domains. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang trust list* *-o* *--fresh* *--quiet* *--verbose* [*--format*=__] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Show defined trust domains. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--format*=__:: 37 | Specify output format ('text' or 'json') 38 | 39 | *--fresh*:: 40 | Make sure we use fresh (i.e. non-cached) resources. 41 | 42 | *-o*, *--offline*:: 43 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 44 | 45 | *--quiet*:: 46 | jbang will be quiet, only print when error occurs. 47 | 48 | *--verbose*:: 49 | jbang will be verbose on what it does. 50 | 51 | // end::picocli-generated-man-section-options[] 52 | 53 | // tag::picocli-generated-man-section-arguments[] 54 | // end::picocli-generated-man-section-arguments[] 55 | 56 | // tag::picocli-generated-man-section-commands[] 57 | // end::picocli-generated-man-section-commands[] 58 | 59 | // tag::picocli-generated-man-section-exit-status[] 60 | // end::picocli-generated-man-section-exit-status[] 61 | 62 | // tag::picocli-generated-man-section-footer[] 63 | // end::picocli-generated-man-section-footer[] 64 | 65 | // end::picocli-generated-full-manpage[] 66 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-trust-remove.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-trust-remove(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-trust-remove - Remove trust domains. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang trust remove* *-o* *--fresh* *--quiet* *--verbose* __... 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Remove trust domains. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | == Arguments 52 | 53 | __...:: 54 | Rules for trusted sources 55 | 56 | // end::picocli-generated-man-section-arguments[] 57 | 58 | // tag::picocli-generated-man-section-commands[] 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-wrapper-install.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-wrapper-install(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-wrapper-install - Install/Setup jbang as a `wrapper` script in a folder 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang wrapper install* *-o* [*-f*] *--fresh* *--quiet* *--verbose* [*-d*=__] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Install/Setup jbang as a `wrapper` script in a folder 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *-d*, *--dir*=__:: 37 | The folder to install the wrapper into. 38 | 39 | *-f*, *--force*:: 40 | Force installation of wrapper even if files already exist 41 | 42 | *--fresh*:: 43 | Make sure we use fresh (i.e. non-cached) resources. 44 | 45 | *-o*, *--offline*:: 46 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 47 | 48 | *--quiet*:: 49 | jbang will be quiet, only print when error occurs. 50 | 51 | *--verbose*:: 52 | jbang will be verbose on what it does. 53 | 54 | // end::picocli-generated-man-section-options[] 55 | 56 | // tag::picocli-generated-man-section-arguments[] 57 | // end::picocli-generated-man-section-arguments[] 58 | 59 | // tag::picocli-generated-man-section-commands[] 60 | // end::picocli-generated-man-section-commands[] 61 | 62 | // tag::picocli-generated-man-section-exit-status[] 63 | // end::picocli-generated-man-section-exit-status[] 64 | 65 | // tag::picocli-generated-man-section-footer[] 66 | // end::picocli-generated-man-section-footer[] 67 | 68 | // end::picocli-generated-full-manpage[] 69 | -------------------------------------------------------------------------------- /docs/modules/cli/pages/jbang-wrapper.adoc: -------------------------------------------------------------------------------- 1 | // This is a generated documentation file based on picocli 2 | // To change it update the picocli code or the genrator 3 | // tag::picocli-generated-full-manpage[] 4 | // tag::picocli-generated-man-section-header[] 5 | :doctype: manpage 6 | :manmanual: jbang Manual 7 | :man-linkstyle: pass:[blue R < >] 8 | = jbang-wrapper(1) 9 | 10 | // end::picocli-generated-man-section-header[] 11 | 12 | // tag::picocli-generated-man-section-name[] 13 | == Name 14 | 15 | jbang-wrapper - Manage jbang wrapper for a folder. 16 | 17 | // end::picocli-generated-man-section-name[] 18 | 19 | // tag::picocli-generated-man-section-synopsis[] 20 | == Synopsis 21 | 22 | *jbang wrapper* *-o* *--fresh* *--quiet* *--verbose* [COMMAND] 23 | 24 | // end::picocli-generated-man-section-synopsis[] 25 | 26 | // tag::picocli-generated-man-section-description[] 27 | == Description 28 | 29 | Manage jbang wrapper for a folder. 30 | 31 | // end::picocli-generated-man-section-description[] 32 | 33 | // tag::picocli-generated-man-section-options[] 34 | == Options 35 | 36 | *--fresh*:: 37 | Make sure we use fresh (i.e. non-cached) resources. 38 | 39 | *-o*, *--offline*:: 40 | Work offline. Fail-fast if dependencies are missing. No connections will be attempted 41 | 42 | *--quiet*:: 43 | jbang will be quiet, only print when error occurs. 44 | 45 | *--verbose*:: 46 | jbang will be verbose on what it does. 47 | 48 | // end::picocli-generated-man-section-options[] 49 | 50 | // tag::picocli-generated-man-section-arguments[] 51 | // end::picocli-generated-man-section-arguments[] 52 | 53 | // tag::picocli-generated-man-section-commands[] 54 | == Commands 55 | 56 | xref:jbang-wrapper-install.adoc[*install*]:: 57 | Install/Setup jbang as a `wrapper` script in a folder 58 | 59 | // end::picocli-generated-man-section-commands[] 60 | 61 | // tag::picocli-generated-man-section-exit-status[] 62 | // end::picocli-generated-man-section-exit-status[] 63 | 64 | // tag::picocli-generated-man-section-footer[] 65 | // end::picocli-generated-man-section-footer[] 66 | 67 | // end::picocli-generated-full-manpage[] 68 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | /classpath_example.class 2 | /script.class 3 | -------------------------------------------------------------------------------- /examples/readme.adoc: -------------------------------------------------------------------------------- 1 | == Examples 2 | 3 | Examples are no longer included with jbang, instead see https://github.com/jbangdev/jbang-examples 4 | 5 | You can list (and then run) these examples directly with `jbang`: 6 | 7 | [source,shell] 8 | ---- 9 | jbang alias list jbangdev/jbang-examples 10 | ---- 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /images/jbang_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/images/jbang_icon.png -------------------------------------------------------------------------------- /images/jbang_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/images/jbang_logo.png -------------------------------------------------------------------------------- /itests/JULAgent.java: -------------------------------------------------------------------------------- 1 | //JAVAAGENT 2 | public class JULAgent { 3 | 4 | public static void premain(String agentArgs, java.lang.instrument.Instrumentation instrumentation) { 5 | System.out.println(agentArgs); 6 | } 7 | } -------------------------------------------------------------------------------- /itests/JULTest.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.logging.Logger; 3 | 4 | /** 5 | * Just some application 6 | * @author Phillip Kruger (phillip.kruger@redhat.com) 7 | */ 8 | public class JULTest { 9 | private static final Logger log = Logger.getLogger(JULTest.class.getName()); 10 | 11 | public void printSomeStuff(String message){ 12 | log.info("info " + message); 13 | log.finest("finest " + message); 14 | 15 | } 16 | 17 | 18 | public static void main(String[] args) { 19 | new JULTest().printSomeStuff(args[0]); 20 | } 21 | } -------------------------------------------------------------------------------- /itests/RootOne.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //SOURCES nested/*.java 4 | //SOURCES othernested/*.java 5 | 6 | import static java.lang.System.*; 7 | 8 | public class RootOne { 9 | 10 | public static void main(String... args) 11 | { 12 | out.println(nested.NestedOne.class.getName()); 13 | out.println(nested.NestedTwo.class.getName()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /itests/Two.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //SOURCES gh_*.java 4 | 5 | import static java.lang.System.*; 6 | 7 | public class Two { 8 | 9 | public static void main(String... args) { 10 | out.println("Hello World"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /itests/alltags.java: -------------------------------------------------------------------------------- 1 | 2 | //REPOS dummy=http://dummy 3 | //DEPS dummy.org:dummy:1.2.3 4 | 5 | //SOURCES Two.java 6 | //SOURCES nested/*.java 7 | 8 | //FILES res/resource.properties renamed.properties=res/resource.properties 9 | //FILES META-INF/application.properties=res/resource.properties 10 | 11 | //COMPILE_OPTIONS --enable-preview --verbose 12 | //RUNTIME_OPTIONS --add-opens java.base/java.net=ALL-UNNAMED 13 | //NATIVE_OPTIONS -O1 -d 14 | 15 | //JAVA 11+ 16 | //MAIN mainclass 17 | //MODULE mymodule 18 | //DESCRIPTION some description 19 | //GAV example.org:alltags:1.2.3 20 | //CDS 21 | //PREVIEW 22 | //MANIFEST one=1 two=2 three=3 23 | //JAVAAGENT 24 | 25 | public class alltags { 26 | public static void main(String... args) { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /itests/bar/Bar.java: -------------------------------------------------------------------------------- 1 | import static java.lang.System.*; 2 | public class Bar { 3 | public static void main(String... args) { 4 | out.println("Hello World"); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /itests/basic.jsh: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS org.apache.commons:commons-lang3:3.12.0 4 | 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | System.out.println(StringUtils.center("Hello World", 20)); 8 | -------------------------------------------------------------------------------- /itests/brokenresource.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //FILES renamed.properties=resourcethatdoesnotexist.properties 3 | 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | 7 | class resource { 8 | 9 | public static void main(String[] args) throws Exception { 10 | Properties prop = new Properties(); 11 | try(InputStream is = resource.class.getClassLoader().getResourceAsStream("resource.properties")) { 12 | prop.load(is); 13 | } 14 | System.out.println("hello " + prop.getProperty("message")); 15 | } 16 | } -------------------------------------------------------------------------------- /itests/build.jbang: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | DEPS info.picocli:picocli:4.6.3 3 | DESCRIPTION For testing purposes 4 | GAV dev.jbang.itests:quote 5 | SOURCES quote_notags.java 6 | JAVA_OPTIONS -Dfoo=bar "-Dbar=aap noot mies" 7 | -------------------------------------------------------------------------------- /itests/classpath_example.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS log4j:log4j:1.2.17 4 | 5 | import static java.lang.System.out; 6 | 7 | import org.apache.log4j.Logger; 8 | import org.apache.log4j.BasicConfigurator; 9 | 10 | import java.util.Arrays; 11 | 12 | class classpath_example { 13 | 14 | static final Logger logger = Logger.getLogger(classpath_example.class); 15 | 16 | public static void main(String[] args) { 17 | BasicConfigurator.configure(); 18 | logger.info("Welcome to jbang"); 19 | 20 | Arrays.asList(args).forEach(arg -> logger.warn("arg: " + arg)); 21 | } 22 | } -------------------------------------------------------------------------------- /itests/classpath_log.groovy: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS log4j:log4j:1.2.17 4 | 5 | import org.apache.log4j.Logger 6 | import org.apache.log4j.BasicConfigurator 7 | 8 | class classpath_log { 9 | 10 | static final Logger logger = Logger.getLogger(classpath_log) 11 | 12 | static void main(String[] args) { 13 | BasicConfigurator.configure() 14 | args.each { arg -> println(arg) } 15 | } 16 | } 17 | 18 | // gradle run --args="1 2 3" 19 | -------------------------------------------------------------------------------- /itests/classpath_log.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS log4j:log4j:1.2.17 4 | 5 | import static java.lang.System.out; 6 | 7 | import org.apache.log4j.Logger; 8 | import org.apache.log4j.BasicConfigurator; 9 | 10 | import java.util.Arrays; 11 | 12 | class classpath_log { 13 | 14 | static final Logger logger = Logger.getLogger(classpath_log.class); 15 | 16 | public static void main(String[] args) { 17 | BasicConfigurator.configure(); 18 | Arrays.asList(args).forEach(arg -> out.println(arg)); 19 | } 20 | } -------------------------------------------------------------------------------- /itests/classpath_log.kt: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS log4j:log4j:1.2.17 4 | 5 | import org.apache.log4j.Logger 6 | import org.apache.log4j.BasicConfigurator 7 | 8 | class classpath_log { 9 | 10 | companion object { 11 | private val logger: Logger = Logger.getLogger(classpath_log::class.java) 12 | 13 | @JvmStatic 14 | fun main(args: Array) { 15 | BasicConfigurator.configure() 16 | args.forEach { println(it) } 17 | } 18 | } 19 | } 20 | 21 | // gradle run --args="1 2 3" 22 | -------------------------------------------------------------------------------- /itests/classpath_log_bom.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS org.apache.logging.log4j:log4j-bom:2.24.3@pom 4 | //DEPS org.apache.logging.log4j:log4j-api 5 | //DEPS org.apache.logging.log4j:log4j-core 6 | 7 | import static java.lang.System.out; 8 | 9 | import java.util.Arrays; 10 | 11 | import org.apache.logging.log4j.LogManager; 12 | import org.apache.logging.log4j.Logger; 13 | import org.apache.logging.log4j.core.config.Configurator; 14 | import org.apache.logging.log4j.core.config.DefaultConfiguration; 15 | 16 | class classpath_log_bom { 17 | 18 | static final Logger logger = LogManager.getLogger(classpath_log_bom.class); 19 | 20 | public static void main(String[] args) { 21 | Configurator.initialize(new DefaultConfiguration()); 22 | Arrays.asList(args).forEach(arg -> out.println(arg)); 23 | } 24 | } -------------------------------------------------------------------------------- /itests/classpath_log_grab.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | import static java.lang.System.out; 4 | 5 | import org.apache.log4j.Logger; 6 | import org.apache.log4j.BasicConfigurator; 7 | 8 | import java.util.Arrays; 9 | 10 | import groovy.lang.Grab; 11 | import groovy.lang.Grapes; 12 | 13 | @Grapes({ 14 | @Grab(group="org.codehaus.groovy", module="groovy", version="2.5.8"), 15 | @Grab(module = "log4j", group = "log4j", version = "1.2.17") 16 | }) 17 | class classpath_log { 18 | 19 | static final Logger logger = Logger.getLogger(classpath_log.class); 20 | 21 | public static void main(String[] args) { 22 | BasicConfigurator.configure(); 23 | Arrays.asList(args).forEach(arg -> out.println(arg)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /itests/classpath_log_grab_with_ranges.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | import org.apache.log4j.Logger; 4 | import org.apache.log4j.BasicConfigurator; 5 | 6 | import java.util.Arrays; 7 | 8 | import groovy.lang.Grab; 9 | import groovy.lang.Grapes; 10 | import groovy.lang.GrabResolver; 11 | 12 | @GrabResolver("central") 13 | @Grapes({ 14 | @Grab(group="ch.qos.reload4j", module="reload4j", version="[1.2.18,1.2.19)"), 15 | @Grab(group = "org.apache.groovy", module = "groovy", version = "4.0.0"), 16 | }) 17 | class classpath_log_grab_with_ranges { 18 | 19 | static final Logger logger = Logger.getLogger(classpath_log_grab_with_ranges.class); 20 | 21 | public static void main(String[] args) { 22 | BasicConfigurator.configure(); 23 | logger.info("Welcome to jbang"); 24 | 25 | Arrays.asList(args).forEach(arg -> logger.warn("arg: " + arg)); 26 | logger.info("Hello from Java!"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /itests/classpath_main.kt: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS log4j:log4j:1.2.17 4 | 5 | import org.apache.log4j.Logger 6 | import org.apache.log4j.BasicConfigurator 7 | 8 | fun main(args: Array) { 9 | args.forEach { println(it) } 10 | } 11 | 12 | // gradle run --args="1 2 3" 13 | -------------------------------------------------------------------------------- /itests/deps.jsh: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //DEPS https://github.com/blocoio/faker/tree/1.2.8 3 | 4 | import io.bloco.faker.Faker; 5 | 6 | Faker fake = new Faker("da-DK"); 7 | System.out.println("Fake output: " + fake.name.firstName()); 8 | 9 | -------------------------------------------------------------------------------- /itests/dualclass.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | 4 | import static java.lang.System.*; 5 | 6 | class firstclass { 7 | 8 | } 9 | 10 | public class dualclass { 11 | 12 | public static void main(String... args) { 13 | out.println("Hello " + (args.length>0?args[0]:"World")); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /itests/ec.jsh: -------------------------------------------------------------------------------- 1 | //DEPS org.eclipse.collections:eclipse-collections-api:11.0.0 2 | //DEPS org.eclipse.collections:eclipse-collections:11.0.0 3 | 4 | import org.eclipse.collections.impl.factory.*; 5 | import org.eclipse.collections.impl.collector.*; 6 | 7 | //import static org.eclipse.collections.impl.collector.Collectors2.*; 8 | -------------------------------------------------------------------------------- /itests/echo.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | echo ARGS = %* 4 | :loop 5 | set _arg=%~1 6 | if "%_arg%" == "" goto loopend 7 | echo ARG = %_arg% 8 | shift 9 | goto loop 10 | :loopend 11 | -------------------------------------------------------------------------------- /itests/echo.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | 4 | import static java.lang.System.*; 5 | 6 | public class echo { 7 | 8 | public static void main(String... args) { 9 | for(int i = 0; i { 20 | 21 | @CommandLine.Option(names={"--token", "-t"}, description = "GitHub token", defaultValue = "${GITHUB_TOKEN}", required = true) 22 | private String token; 23 | 24 | @CommandLine.Option(names={"--repo", "-r"}, description = "GitHub Repository (/)", required = true) 25 | private String repo; 26 | 27 | public static void main(String... args) { 28 | int exitCode = new CommandLine(new gh_release_stats()).execute(args); 29 | System.exit(exitCode); 30 | } 31 | 32 | @Override 33 | public Integer call() throws Exception { 34 | GitHub gh = GitHub.connect("", token); 35 | 36 | 37 | out.println("release date, release name, name, size, count"); 38 | 39 | for (GHRelease release:gh.getRepository(repo).listReleases().toList()) { 40 | 41 | List assets = release.getAssets(); 42 | for(GHAsset asset : assets) { 43 | out.printf("%tF,%s,%s,%s,%s\n", 44 | release.getPublished_at(), 45 | release.getName(), 46 | asset.getName(), 47 | asset.getSize(), 48 | asset.getDownloadCount()); 49 | } 50 | } 51 | return 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /itests/hello.jsh: -------------------------------------------------------------------------------- 1 | System.out.println(System.getProperty("value")); 2 | -------------------------------------------------------------------------------- /itests/hellojar.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/itests/hellojar.jar -------------------------------------------------------------------------------- /itests/hellojsh: -------------------------------------------------------------------------------- 1 | // example of jsh without suffix. 2 | // use jbang --jsh to force it. 3 | System.out.println(args[0]); 4 | -------------------------------------------------------------------------------- /itests/helloworld.groovy: -------------------------------------------------------------------------------- 1 | //JAVA 11 2 | println("Hello Groovy!") 3 | println("hello ".repeat(2)) -------------------------------------------------------------------------------- /itests/helloworld.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //NATIVE_OPTIONS -O1 4 | //RUNTIME_OPTIONS -Dfoo=bar "-Dbar=aap noot mies" 5 | //MANIFEST foo bar=baz baz=${bazprop:nada} 6 | 7 | import static java.lang.System.*; 8 | 9 | public class helloworld { 10 | 11 | public static void main(String... args) { 12 | out.println("Hello " + (args.length>0?args[0]:"World")); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /itests/helloworld.jsh: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | System.out.println("Hello " + (args.length>0?args[0]:"World")); 4 | 5 | /exit 6 | -------------------------------------------------------------------------------- /itests/helloworld.kt: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //NATIVE_OPTIONS -O1 4 | //RUNTIME_OPTIONS -Dfoo=bar "-Dbar=aap noot mies" 5 | //MANIFEST foo bar=baz baz=${bazprop:nada} 6 | 7 | class helloworld { 8 | fun main(vararg args: String) { 9 | println("Hello " + if (args.length>0) args[0] else "World")); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /itests/java4321.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //JAVA 4321 4 | 5 | import static java.lang.System.*; 6 | 7 | public class java4321 { 8 | 9 | public static void main(String... args) { 10 | out.println("java:" + System.getProperty("java.version")); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /itests/keyvalue.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class keyvalue { 4 | 5 | public static void main(String[] args) { 6 | Arrays.stream(args).forEach(System.out::println); 7 | } 8 | } -------------------------------------------------------------------------------- /itests/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WARN 7 | 8 | 9 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | 15 | target/karate.log 16 | 17 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /itests/main.jsh: -------------------------------------------------------------------------------- 1 | //SOURCES funcs.jsh 2 | 3 | print("hello"); 4 | -------------------------------------------------------------------------------- /itests/nakedmain/classinstance.java: -------------------------------------------------------------------------------- 1 | //JAVA 21+ 2 | //PREVIEW 3 | class classinstance { 4 | void main(String... args) { 5 | 6 | System.out.println("Hello " + args[0]); 7 | } 8 | } -------------------------------------------------------------------------------- /itests/nakedmain/noclass.java: -------------------------------------------------------------------------------- 1 | //JAVA 21+ 2 | //PREVIEW 3 | 4 | void main() { 5 | System.out.println("Hello!"); 6 | } -------------------------------------------------------------------------------- /itests/nakedmain/noclasswithargs.java: -------------------------------------------------------------------------------- 1 | //JAVA 21+ 2 | //PREVIEW 3 | 4 | void main(String... args) { 5 | System.out.println("Hello " + args[0]); 6 | } -------------------------------------------------------------------------------- /itests/nested/NestedOne.java: -------------------------------------------------------------------------------- 1 | package nested; 2 | 3 | public class NestedOne { 4 | 5 | } -------------------------------------------------------------------------------- /itests/nested/NestedTwo.java: -------------------------------------------------------------------------------- 1 | package nested; 2 | 3 | import othernested.OtherThree; 4 | 5 | public class NestedTwo { 6 | 7 | public static void main(String... args) { 8 | System.out.println(NestedOne.class.getName()); 9 | 10 | System.out.println(OtherThree.class.getName()); 11 | } 12 | } -------------------------------------------------------------------------------- /itests/noints.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //NOINTEGRATIONS 3 | 4 | public class noints { 5 | public static void main(String... args) { 6 | System.out.println("No integrations here"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /itests/one.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //SOURCES Two.java 4 | 5 | import static java.lang.System.*; 6 | 7 | public class one { 8 | 9 | public static void main(String... args) { 10 | out.println(Two.class.getName()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /itests/onedep.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //DEPS Two.java 3 | 4 | public class onedep { 5 | public static void main(String... args) { 6 | Two.main(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /itests/othernested/OtherThree.java: -------------------------------------------------------------------------------- 1 | package othernested; 2 | 3 | public class OtherThree { 4 | 5 | } -------------------------------------------------------------------------------- /itests/quote.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //DEPS info.picocli:picocli:4.6.3 3 | //DESCRIPTION For testing purposes 4 | //GAV dev.jbang.itests:quote 5 | 6 | import java.util.Map; 7 | 8 | import picocli.CommandLine; 9 | import picocli.CommandLine.Option; 10 | 11 | public class quote implements Runnable { 12 | @Option(names = "-fix", split = "\\|") 13 | Map message; 14 | 15 | @Option(names = "-other") 16 | String other; 17 | 18 | @Override 19 | public void run() { 20 | if(System.getProperty("value")!=null) { 21 | System.out.print("value: " + System.getProperty("value") + " "); 22 | } 23 | System.out.println("other: [" + (other==null?"":other) + "] " + "fix: " + message); 24 | } 25 | 26 | public static void main(String[] args) { 27 | new CommandLine(new quote()).execute(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /itests/quote_notags.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.Map; 3 | 4 | import picocli.CommandLine; 5 | import picocli.CommandLine.Option; 6 | 7 | public class quote_notags implements Runnable { 8 | @Option(names = "-fix", split = "\\|") 9 | Map message; 10 | 11 | @Option(names = "-other") 12 | String other; 13 | 14 | @Override 15 | public void run() { 16 | if(System.getProperty("value")!=null) { 17 | System.out.print("value: " + System.getProperty("value") + " "); 18 | } 19 | System.out.println("other: [" + (other==null?"":other) + "] " + "fix: " + message); 20 | } 21 | 22 | public static void main(String[] args) { 23 | new CommandLine(new quote_notags()).execute(args); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /itests/readme.adoc: -------------------------------------------------------------------------------- 1 | == How to run integration tests 2 | 3 | In addition to the unit tests driven by gradle this directory 4 | contains tests using https://github.com/andamira/aserta[aserta]. 5 | 6 | A bash driven testing suite runner which allows to do easy testing 7 | running in a shell. 8 | 9 | To run the tests first make sure you've built jbang first, added `jbang` to the path, cd to this directory and run the link:test_suite.sh[test_suite.sh]. 10 | 11 | [source, bash] 12 | ---- 13 | ./gradlew build installDist 14 | export PATH=`pwd`/build/install/jbang/bin:$PATH 15 | cd itests 16 | ./test_suite.sh 17 | ---- 18 | 19 | == Integration tests 20 | 21 | Historically the integration tests were done using Karate .feature files. 22 | Today that is all ported to using junit ITests using Allure for capturing the results. 23 | 24 | To run the tests just do a `./gradlew integrationTest` or `just itest` from the root. 25 | 26 | To open the test report do a `just openitest` from the root. -------------------------------------------------------------------------------- /itests/readme.md: -------------------------------------------------------------------------------- 1 | ## Markdown Scripts 2 | 3 | It is possible to write scripts using markdown. 4 | 5 | JBang will extract code found in `java` or `jsh` or `jshelllanguage` code blocks. 6 | 7 | Try run `jbang readme.md`. 8 | 9 | ```java 10 | class Demo { 11 | void test() { 12 | System.out.println("Hello, World!"); 13 | } 14 | } 15 | ``` 16 | 17 | It will take all blocks and execute via jshell by default and if main method found it will treat it as a .java file. 18 | 19 | ```jshelllanguage 20 | new Demo().test(); 21 | ``` 22 | 23 | You can of course also use `//DEPS` in the code blocks. 24 | 25 | ```jsh 26 | //DEPS com.github.lalyos:jfiglet:0.0.8 27 | import com.github.lalyos.jfiglet.FigletFont; 28 | 29 | System.out.println(FigletFont.convertOneLine( 30 | "Hello " + ((args.length>0)?args[0]:"jbang"))); 31 | ``` 32 | 33 | Oh, and did you notice it handled arguments too? 34 | 35 | ```java 36 | if(args.length==0) { 37 | System.out.println("You have no arguments!"); 38 | } else { 39 | System.out.printf("You have %s arguments! First is %s", args.length, args[0]); 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /itests/res/resource.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //FILES resource.properties renamed.properties=resource.properties 3 | //FILES META-INF/application.properties=resource.properties 4 | 5 | import java.io.InputStream; 6 | import java.util.Properties; 7 | 8 | class resource { 9 | 10 | public static void main(String[] args) throws Exception { 11 | Properties prop = new Properties(); 12 | try(InputStream is = resource.class.getClassLoader().getResourceAsStream("resource.properties")) { 13 | prop.load(is); 14 | } 15 | System.out.println("hello " + prop.getProperty("message")); 16 | } 17 | } -------------------------------------------------------------------------------- /itests/res/resource.properties: -------------------------------------------------------------------------------- 1 | message=properties -------------------------------------------------------------------------------- /itests/res/sub/sub.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/itests/res/sub/sub.properties -------------------------------------------------------------------------------- /itests/res/test.properties: -------------------------------------------------------------------------------- 1 | message=properties -------------------------------------------------------------------------------- /itests/resource.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //FILES resource.properties renamed.properties=resource.properties 3 | //FILES META-INF/application.properties=resource.properties 4 | 5 | import java.io.InputStream; 6 | import java.util.Properties; 7 | 8 | class resource { 9 | 10 | public static void main(String[] args) throws Exception { 11 | Properties prop = new Properties(); 12 | try(InputStream is = resource.class.getClassLoader().getResourceAsStream("resource.properties")) { 13 | prop.load(is); 14 | } 15 | System.out.println("hello " + prop.getProperty("message")); 16 | } 17 | } -------------------------------------------------------------------------------- /itests/resource.properties: -------------------------------------------------------------------------------- 1 | message=properties -------------------------------------------------------------------------------- /itests/resources.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //FILES res/*.properties 3 | 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | 7 | class resources { 8 | 9 | public static void main(String[] args) throws Exception { 10 | Properties prop = new Properties(); 11 | try(InputStream is = resources.class.getClassLoader().getResourceAsStream("resource.properties")) { 12 | prop.load(is); 13 | } 14 | System.out.println("hello " + prop.getProperty("message")); 15 | } 16 | } -------------------------------------------------------------------------------- /itests/resourcesmnt.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //FILES somedir=res/*.properties 3 | 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | 7 | class resourcesmnt { 8 | 9 | public static void main(String[] args) throws Exception { 10 | Properties prop = new Properties(); 11 | try(InputStream is = resourcesmnt.class.getClassLoader().getResourceAsStream("somedir/resource.properties")) { 12 | prop.load(is); 13 | } 14 | System.out.println("hello " + prop.getProperty("message")); 15 | } 16 | } -------------------------------------------------------------------------------- /itests/runkotlin.kt: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //DEPS com.github.zafarkhaja:java-semver:0.9.0 4 | //DEPS com.fasterxml.jackson.core:jackson-databind:2.15.2 5 | //DEPS com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2 6 | 7 | import com.fasterxml.jackson.databind.JsonNode 8 | import com.github.zafarkhaja.semver.Version 9 | import com.fasterxml.jackson.databind.node.ObjectNode 10 | import com.fasterxml.jackson.dataformat.xml.XmlMapper 11 | import java.util.stream.StreamSupport 12 | import java.util.Spliterators 13 | 14 | fun main() { 15 | // props to Chris Dellaway for the pointer to this 16 | val url = "https://oss.sonatype.org/content/repositories/snapshots/org/mongodb/mongodb-driver-sync/maven-metadata.xml" 17 | val mapper = XmlMapper() 18 | val min: String = System.getenv().getOrDefault("DRIVER_MIN", "5.0.0") 19 | val driverMinimum = Version.valueOf(min) 20 | var document = mapper.readTree(java.net.URL(url)) 21 | val versions: JsonNode = document 22 | .get("versioning") 23 | .get("versions") 24 | .get("version") 25 | 26 | val result = versions.elements() 27 | .asSequence() 28 | .map{ it.asText() } 29 | .map { Version.valueOf(it) } 30 | .filter { it.greaterThanOrEqualTo(driverMinimum) } 31 | .sorted() 32 | .toList() 33 | 34 | println(result.last()) 35 | println("SUCCESS!") 36 | } 37 | -------------------------------------------------------------------------------- /itests/selfdep.java: -------------------------------------------------------------------------------- 1 | //DEPS selfdep.java 2 | 3 | class selfdep { 4 | public static void main(String... args) { 5 | System.out.println("Hello, world!"); 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /itests/sources.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | //SOURCES quote.java 4 | 5 | public class sources { 6 | public static void main(String[] args) { 7 | new quote().main(args); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /itests/sources/yang.java: -------------------------------------------------------------------------------- 1 | //SOURCES **.java -------------------------------------------------------------------------------- /itests/sources/ying.java: -------------------------------------------------------------------------------- 1 | //SOURCES yang.java 2 | -------------------------------------------------------------------------------- /itests/templates/test.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | public class {baseName}Test { 4 | } 5 | -------------------------------------------------------------------------------- /itests/test.bat: -------------------------------------------------------------------------------- 1 | java test.java 2 | echo %ERRORLEVEL% 3 | -------------------------------------------------------------------------------- /itests/test.java: -------------------------------------------------------------------------------- 1 | public class test { 2 | 3 | public static void main(String[] args) { 4 | System.out.println("error 35"); 5 | System.exit(35); 6 | } 7 | } -------------------------------------------------------------------------------- /itests/with space/helloworld.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | // //DEPS 3 | //RUNTIME_OPTIONS -Dfoo=bar "-Dbar=aap noot mies" 4 | //MANIFEST foo bar=baz baz=${bazprop:nada} 5 | 6 | import static java.lang.System.*; 7 | 8 | public class helloworld { 9 | 10 | public static void main(String... args) { 11 | out.println("Hello " + (args.length>0?args[0]:"World")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /misc/bootstrap_jbang.sh: -------------------------------------------------------------------------------- 1 | function _in_path() { command -v "$1" >/dev/null 2>&1; } 2 | _in_path jbang || { 3 | export SCRATCH=`mktemp -d -t "$(basename $0).XXX"` 4 | echo "Downloading latest jbang from https://github.com/jbangdev/jbang" 5 | 6 | curl -s https://api.github.com/repos/jbangdev/jbang/releases/latest \ 7 | | grep "browser_download_url.*.zip\"" | cut -d : -f 2,3 | tr -d \" \ 8 | | xargs curl -s -L > $SCRATCH\jbang.zip 9 | unzip -q $SCRATCH\jbang.zip -d $SCRATCH 10 | mv $SCRATCH/jbang*/bin/jbang* /usr/local/bin 11 | chmod +x /usr/local/bin/jbang 12 | rm -rf $SCRATCH 13 | } -------------------------------------------------------------------------------- /misc/demos/basic-jbang.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ######################## 4 | # include the magic 5 | ######################## 6 | . ./demo-magic.sh 7 | 8 | 9 | ######################## 10 | # Configure the options 11 | ######################## 12 | 13 | # 14 | # speed at which to simulate typing. bigger num = faster 15 | # 16 | TYPE_SPEED=40 17 | 18 | # 19 | # custom prompt 20 | # 21 | # see http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/bash-prompt-escape-sequences.html for escape sequences 22 | # 23 | #DEMO_PROMPT="$ " 24 | DEMO_CMD_COLOR=$WHITE 25 | DEMO_COMMENT_COLOR=$GREEN 26 | 27 | # text color 28 | 29 | # hide the evidence 30 | clear 31 | 32 | pei "# Lets create a directory with a java example made with jbang" 33 | pei "mkdir example; cd example" 34 | pei "jbang init hello.java" 35 | pei "# Now we run it using jbang" 36 | pei "jbang hello.java" 37 | pei "# In a bash or zsh shell you run the file directly" 38 | pei "./hello.java" 39 | pei "# That was the basics - now lets create an example using 3rd party dependencies" 40 | pei "jbang init -t cli hellocli.java" 41 | pei "# This creates a hello world using picocli and gives you built in help" 42 | pei "./hellocli.java --help" 43 | pei "./hellocli.java JBANG!" 44 | pei "# Lets now edit it in IDE of choice - in this case vim" 45 | p "vim \`jbang edit hellocli.java\`" 46 | vim `jbang edit hellocli.java` 47 | pei "./hellocli.java JBang with a longer command line" 48 | pei "# That is the basics of jbang!" 49 | pei "# Download from https://jbang.dev runs in Windows, Linux, OSX, Containers, GitHub actions and more..." 50 | # run command behind 51 | cd .. && rm -rf example 52 | 53 | # show a prompt so as not to reveal our true nature after 54 | # the demo has concluded 55 | # p "" -------------------------------------------------------------------------------- /misc/demos/readme.adoc: -------------------------------------------------------------------------------- 1 | = Scripts for jbang demos 2 | 3 | To record run: 4 | 5 | `asciinema rec -c "./basic-jbang.sh" video` 6 | 7 | Strip long pauses: 8 | 9 | `asciinema-edit quantize --range 0.3 ./video > realvideo` 10 | 11 | when okey, upload: 12 | 13 | `asciinema upload realvideo` 14 | 15 | -------------------------------------------------------------------------------- /misc/promotesnap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ######################################################################## 3 | ### Release snap 4 | 5 | set -e 6 | 7 | jbang_version=`ls build/distributions/jbang-*.*.zip | sed -e 's/.*jbang-\(.*\).zip/\1/g'` 8 | echo "Promoting jbang snap with version $jbang_version from `pwd`" 9 | 10 | snapcraft list-revisions jbang | grep ${jbang_version} | awk '{print $1}' | tac | xargs -n1 -I {} snapcraft release jbang {} latest/stable 11 | 12 | ## to test use `sudo snap install jbang` -------------------------------------------------------------------------------- /misc/proxy/README.md: -------------------------------------------------------------------------------- 1 | # Testing with a proxy 2 | 3 | You can use the `docker-compose.yml` file in this folder to test how 4 | JBang behaves on a system that only has access to the Internet via a 5 | proxy. 6 | 7 | To do this you need to have `docker-compose` installed and then from 8 | this folder you can run the command: 9 | 10 | ``` 11 | docker-compose up -d tinyproxy 12 | ``` 13 | 14 | Which will start up a proxy server on an internal container network. 15 | When that's done you can run a container that has JBang pre-installed: 16 | 17 | ``` 18 | docker-compose run --rm jbang 19 | ``` 20 | 21 | You'll now have access to a shell in a container that can only access 22 | the Internet via the proxy at the URL `tinyproxy:8888`. Environment 23 | variables have already been set for Linux itself so `curl` will work 24 | just fine. Likewise `~/.m2/settings.xml` is setup so that Maven will 25 | honor the proxy settings too. 26 | 27 | Setting the proxy options for Java requires a bit more work and doesn't 28 | always work. One way is to inherit the settings from the OS, like this: 29 | 30 | ``` 31 | export JAVA_TOOL_OPTIONS="-Djava.net.useSystemProxies=true" 32 | ``` 33 | 34 | The other option is to set it explicitly: 35 | 36 | ``` 37 | export JAVA_TOOL_OPTIONS="-Dhttp.proxyHost=tinyproxy -Dhttp.proxyPort=8888 -Dhttps.proxyHost=tinyproxy -Dhttps.proxyPort=8888" 38 | ``` 39 | -------------------------------------------------------------------------------- /misc/proxy/config/settings.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | tiny-http-proxy 9 | true 10 | http 11 | tinyproxy 12 | 8888 13 | 14 | 15 | 16 | tiny-https-proxy 17 | true 18 | https 19 | tinyproxy 20 | 8888 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /misc/proxy/config/tinyproxy.conf: -------------------------------------------------------------------------------- 1 | # Uncomment if you want to test proxy authentication 2 | #BasicAuth test test 3 | 4 | Port 8888 5 | 6 | -------------------------------------------------------------------------------- /misc/proxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | version: "3.9" 3 | services: 4 | 5 | tinyproxy: 6 | image: vimagick/tinyproxy@sha256:72b441b95ee1e641af948f68f09492f9f795ead72b73954414e339168c98ad8c 7 | networks: 8 | - no-internet 9 | - internet 10 | volumes: 11 | - ./config/tinyproxy.conf:/etc/tinyproxy/tinyproxy.conf 12 | restart: unless-stopped 13 | 14 | jbang: 15 | image: jbangdev/jbang-action@sha256:81395456d0a186557f11a96430517e198592304b2deb3a1408b27848ef1986cc 16 | stdin_open: true 17 | tty: true 18 | entrypoint: /bin/bash 19 | environment: 20 | - http_proxy=http://tinyproxy:8888 21 | - https_proxy=http://tinyproxy:8888 22 | networks: 23 | - no-internet 24 | volumes: 25 | - ../../build/install/jbang/bin:/jbang/bin:ro 26 | - ../../itests:/itests:ro 27 | - ./config/settings.xml:/root/.m2/settings.xml 28 | working_dir: /itests 29 | 30 | networks: 31 | internet: {} 32 | no-internet: 33 | internal: true 34 | 35 | -------------------------------------------------------------------------------- /misc/updatesnap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ######################################################################## 3 | ### Update snap 4 | 5 | set -e 6 | 7 | jbang_version=`ls build/distributions/jbang-*.*.zip | sed -e 's/.*jbang-\(.*\).zip/\1/g'` 8 | echo "Updating jbang snap with version $jbang_version from `pwd`" 9 | DIST=`ls build/distributions/jbang-${jbang_version}.zip | cut -f1 -d ' '` 10 | sha256=`cat $DIST.sha256` 11 | 12 | rm -rf jbang-snap 13 | git clone https://github.com/jbangdev/jbang-snap.git 14 | 15 | cp build/snap/snapcraft.yaml jbang-snap/snap 16 | 17 | cd jbang-snap 18 | 19 | git config user.name "Max Rydahl Andersen" 20 | git config user.email "max@xam.dk" 21 | 22 | 23 | git add snap/snapcraft.yaml 24 | git commit -m "jbang v${jbang_version}" 25 | git tag -a "v${jbang_version}" -m "jbang v${jbang_version}" 26 | 27 | remote_repo="https://${BREW_USER}:${BREW_GITHUB_TOKEN}@github.com/jbangdev/jbang-snap.git" 28 | echo $remote_repo 29 | 30 | git push "${remote_repo}" --follow-tags 31 | 32 | 33 | ## to test use `sudo snap install jbang --edge --classic` -------------------------------------------------------------------------------- /misc/updatespec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ######################################################################## 3 | ### Update docker 4 | 5 | set -e 6 | 7 | jbang_version=`ls build/distributions/jbang-*.*.zip | sed -e 's/.*jbang-\(.*\).zip/\1/g'` 8 | echo "Updating jbang spec with version $jbang_version from `pwd`" 9 | DIST=`ls build/distributions/jbang-${jbang_version}.zip | cut -f1 -d ' '` 10 | sha256=`cat $DIST.sha256` 11 | 12 | rm -rf jbang-spec 13 | git clone https://github.com/jbangdev/jbang-spec.git 14 | 15 | cp build/spec/jbang.spec jbang-spec/jbang.spec 16 | cd jbang-spec 17 | 18 | git config user.name "Max Rydahl Andersen" 19 | git config user.email "max@xam.dk" 20 | 21 | 22 | git add jbang.spec 23 | git commit -m "jbang v${jbang_version}" 24 | git tag -a "v${jbang_version}" -m "jbang v${jbang_version}" 25 | 26 | remote_repo="https://${BREW_USER}:${BREW_GITHUB_TOKEN}@github.com/jbangdev/jbang-spec.git" 27 | echo $remote_repo 28 | 29 | git push "${remote_repo}" --follow-tags 30 | 31 | 32 | -------------------------------------------------------------------------------- /pipelines.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | (*) --> "Code Pushed" 3 | 4 | if "master" then 5 | -->[true] "Build with Gradle" 6 | --> "Run tests" 7 | -right-> (*) 8 | else 9 | ->[false] "Build with Gradle" 10 | --> "Run tests" 11 | --> "Do github *Draft* release" 12 | -->[Ending process] (*) 13 | endif 14 | @enduml -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:best-practices" 4 | ], 5 | "packageRules": [ 6 | { 7 | "matchPackageNames": ["io.quarkus.qute:qute-core"], 8 | "allowedVersions": "<2.0.0" 9 | }, 10 | { 11 | "groupName": "{{manager}}", 12 | "matchPackageNames": [ 13 | "*" 14 | ] 15 | }, 16 | { 17 | "description": "Wiremock >3 requires Java 11", 18 | "matchPackageNames": ["com.github.tomakehurst:wiremock"], 19 | "allowedVersions": "<3.0.0" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | plugins { 3 | id "com.gradle.enterprise" version "3.7.2" 4 | } 5 | } 6 | 7 | plugins { 8 | id "com.gradle.enterprise" 9 | } 10 | 11 | 12 | // Configuration of com.gradle.enterprise (build scan) plugin 13 | gradleEnterprise { 14 | buildScan { 15 | // Accept the license agreement for com.gradle.build-scan plugin 16 | termsOfServiceUrl = 'https://gradle.com/terms-of-service' 17 | termsOfServiceAgree = 'yes' 18 | 19 | // Always publish scan (no more need for --scan option) 20 | //publishAlways() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/AliasIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class AliasIT extends BaseIT { 8 | 9 | // Scenario: No properties should be displayed for an alias having none 10 | // When command('jbang alias add -f ' + scratch + ' echo.java') 11 | // * match exit == 0 12 | // Then command('jbang alias list -f ' + scratch) 13 | // * match exit == 0 14 | // * match out !contains "Properties" 15 | // Then command('jbang alias remove -f ' + scratch + ' echo') 16 | // * match exit == 0 17 | @Test 18 | public void shouldAddAlias() { 19 | assertThat(shell("jbang alias add -f " + scratch() + " echo.java")).succeeded(); 20 | assertThat(shell("jbang alias list -f " + scratch())).succeeded().outNotContains("Properties"); 21 | assertThat(shell("jbang alias remove -f " + scratch() + " echo")).succeeded(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/AppIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | import static java.lang.System.lineSeparator; 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.condition.DisabledOnOs; 9 | import org.junit.jupiter.api.condition.EnabledOnOs; 10 | import org.junit.jupiter.api.condition.OS; 11 | 12 | import io.qameta.allure.Description; 13 | 14 | public class AppIT extends BaseIT { 15 | 16 | // Scenario: check quotes are kept when wrapped with quotes 17 | // * command('jbang app install --force --name jbang-itest-app-quote echo.java') 18 | // When command('$JBANG_DIR/bin/jbang-itest-app-quote \'foo *\'') 19 | // Then match out == "0:foo *\n" 20 | @Test 21 | @DisabledOnOs(OS.WINDOWS) 22 | @Description("check quotes are kept when wrapped with quotes") 23 | public void shouldKeepQuotes() { 24 | assertThat(shell("jbang app install --force --name jbang-itest-app-quote echo.java")).succeeded(); 25 | assertThat(shell("$JBANG_DIR/bin/jbang-itest-app-quote 'foo *'")).succeeded() 26 | .outIsExactly( 27 | "0:foo *" + lineSeparator()); 28 | } 29 | 30 | // Scenario: check quotes are kept when wrapped with quotes 31 | // * command('jbang app install --force --name jbang-itest-app-quote echo.java') 32 | // When command('%JBANG_DIR%\\bin\\jbang-itest-app-quote.cmd "foo *"') 33 | // Then match out == "0:foo *\n" 34 | @Test 35 | @EnabledOnOs(OS.WINDOWS) 36 | public void shouldKeepQuotesWindows() { 37 | assertThat(shell("jbang app install --force --name jbang-itest-app-quote echo.java")).succeeded(); 38 | assertThat(shell( 39 | "%JBANG_DIR%\\bin\\jbang-itest-app-quote.cmd \"foo *\"" + lineSeparator())) 40 | .succeeded() 41 | .outIsExactly("0:foo *" 42 | + lineSeparator()); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/CommandResult.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | class CommandResult { 7 | List command; 8 | 9 | String out; 10 | String err; 11 | int exit; 12 | 13 | public CommandResult(String out, String err, int exit, String... command) { 14 | this(out, err, exit, Arrays.asList(command)); 15 | 16 | } 17 | 18 | public CommandResult(String out, String err, int exit, List command) { 19 | this.command = command; 20 | this.out = out; 21 | this.err = err; 22 | this.exit = exit; 23 | } 24 | 25 | public List command() { 26 | return command; 27 | } 28 | 29 | public String out() { 30 | return out; 31 | } 32 | 33 | public String err() { 34 | return err; 35 | } 36 | 37 | public int exitCode() { 38 | return exit; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return String.format("Command: [%s]\nexit: %s\nout: %s\nerr: %s", command, exit, out, err); 44 | } 45 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/ConfigIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class ConfigIT extends BaseIT { 8 | 9 | // Feature: config 10 | 11 | // Scenario: Configuration keys can be updated 12 | // When command('jbang config set foo bar') 13 | // * match exit == 0 14 | // When command('jbang config set foo baz') 15 | // * match exit == 0 16 | // Then command('jbang config list') 17 | // * match exit == 0 18 | // * match out contains "foo = baz" 19 | @Test 20 | public void testConfigKeyUpdate() { 21 | assertThat(shell("jbang config set foo bar")) 22 | .succeeded(); 23 | 24 | assertThat(shell("jbang config set foo baz")) 25 | .succeeded(); 26 | 27 | assertThat(shell("jbang config list")) 28 | .succeeded() 29 | .outContains("foo = baz"); 30 | } 31 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/DependenciesIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.util.Collections; 9 | 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class DependenciesIT extends BaseIT { 13 | 14 | // Feature: dependency fetching 15 | 16 | // Scenario: fetch dependencies 17 | // * command('jbang --verbose version') 18 | // When command('jbang classpath_log.java', { JBANG_REPO: scratch + "/newrepo"}) 19 | // Then match err == '[jbang] Resolving dependencies...\n[jbang] 20 | // log4j:log4j:1.2.17\n[jbang] Dependencies resolved\n[jbang] Building jar for 21 | // classpath_log.java...\n' 22 | // And fileexist(scratch + "/newrepo") 23 | // And match exit == 0 24 | @Test 25 | public void testFetchDependencies() { 26 | shell("jbang --verbose version"); 27 | 28 | Path newRepo = scratch().resolve("newrepo"); 29 | assertThat( 30 | shell(Collections.singletonMap("JBANG_REPO", newRepo.toAbsolutePath().toString()), 31 | "jbang classpath_log.java")) 32 | .succeeded() 33 | .errEquals( 34 | "[jbang] Resolving dependencies...\n[jbang] log4j:log4j:1.2.17\n[jbang] Dependencies resolved\n[jbang] Building jar for classpath_log.java...\n" 35 | .replace( 36 | "\n", System.lineSeparator())); 37 | 38 | assertThat(Files.exists(newRepo)).isTrue(); 39 | } 40 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/DeprecatedIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import java.nio.file.Path; 6 | 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.io.TempDir; 9 | 10 | public class DeprecatedIT extends BaseIT { 11 | 12 | // Feature: deprecated and removed features 13 | 14 | // Scenario: --init should error and tell user about alternative 15 | // When command('jbang --init ' + scratch + '/test.java') 16 | // * match exit == 2 17 | // * match err contains "deprecated and now removed" 18 | @Test 19 | public void testInitDeprecated(@TempDir Path scratch) { 20 | Path testFile = scratch.resolve("test.java"); 21 | assertThat(shell("jbang --init " + testFile)) 22 | .failed() 23 | .errContains("deprecated and now removed"); 24 | } 25 | 26 | // Scenario: --trust should error and tell user about alternative 27 | // When command('jbang --trust test.java') 28 | // * match exit == 2 29 | // * match err contains "deprecated and now removed" 30 | @Test 31 | public void testTrustDeprecated() { 32 | assertThat(shell("jbang --trust test.java")) 33 | .failed() 34 | .errContains("deprecated and now removed"); 35 | } 36 | 37 | // Scenario: --trust should error and tell user about alternative 38 | // When command('jbang --edit-live=idea test.java') 39 | // * match exit == 2 40 | // * match err contains "deprecated and now removed" 41 | @Test 42 | public void testEditLiveDeprecated() { 43 | assertThat(shell("jbang --edit-live=idea test.java")) 44 | .failed() 45 | .errContains("deprecated and now removed"); 46 | } 47 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/EditIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class EditIT extends BaseIT { 8 | 9 | // Feature: edit 10 | 11 | // Scenario: edit no-open a file should print to std out 12 | // * command('jbang init hello.java') 13 | // * command('jbang edit -b --no-open hello.java') 14 | // * match err == '[jbang] Creating sandbox for script editing hello.java\n' 15 | // * match out contains 'hello' 16 | @Test 17 | public void testEditNoOpen() { 18 | shell("jbang init hello.java"); 19 | assertThat(shell("jbang edit -b --no-open hello.java")) 20 | .succeeded() 21 | .errEquals( 22 | "[jbang] Creating sandbox for script editing hello.java" 23 | + System.lineSeparator()) 24 | .outContains("hello"); 25 | } 26 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/ExportIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class ExportIT extends BaseIT { 8 | 9 | // Feature: export 10 | 11 | // Scenario: basic export no classpath 12 | // When command('rm helloworld.jar') 13 | // When command('jbang export local helloworld.java') 14 | // Then match err contains "Exported to" 15 | // Then match err contains "helloworld.jar" 16 | @Test 17 | public void testBasicExportNoClasspath() { 18 | shell("rm helloworld.jar"); 19 | assertThat(shell("jbang export local helloworld.java")) 20 | .succeeded() 21 | .errContains("Exported to") 22 | .errContains("helloworld.jar"); 23 | } 24 | 25 | // Scenario: basic export slim no classpath 26 | // When command('rm -rf helloworld.jar lib') 27 | // When command('jbang export portable helloworld.java') 28 | // Then match err contains "Exported to" 29 | // Then match err contains "helloworld.jar" 30 | @Test 31 | public void testBasicExportSlimNoClasspath() { 32 | shell("rm -rf helloworld.jar lib"); 33 | assertThat(shell("jbang export portable helloworld.java")) 34 | .succeeded() 35 | .errContains("Exported to") 36 | .errContains("helloworld.jar"); 37 | } 38 | 39 | // Scenario: basic export classpath 40 | // When command('rm -rf classpath_example.jar lib') 41 | // When command('jbang export portable classpath_example.java') 42 | // Then match err contains "Exported to" 43 | // Then match err contains "classpath_example.jar" 44 | // When command('jbang export portable --force classpath_example.java') 45 | // Then match err contains "Exported to" 46 | // Then match err contains "classpath_example.jar" 47 | @Test 48 | public void testBasicExportClasspath() { 49 | shell("rm -rf classpath_example.jar lib"); 50 | assertThat(shell("jbang export portable classpath_example.java")) 51 | .succeeded() 52 | .errContains("Exported to") 53 | .errContains("classpath_example.jar"); 54 | assertThat(shell("jbang export portable --force classpath_example.java")) 55 | .succeeded() 56 | .errContains("Exported to") 57 | .errContains( 58 | "classpath_example.jar"); 59 | } 60 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/JarIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | import static java.lang.System.lineSeparator; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class JarIT extends BaseIT { 9 | // Feature: launching jars 10 | 11 | // Scenario: java launch file 12 | // When command('jbang helloworld.jar') 13 | // Then match out == "Hello World\n" 14 | @Test 15 | void testJavaLaunchFile() { 16 | assertThat(shell("jbang hellojar.jar")) 17 | .outEquals("Hello World" + lineSeparator()); 18 | } 19 | 20 | // #TODO: find GAV with static void main 21 | // Scenario: java launch GAV 22 | // When command('jbang --main 23 | // picocli.codegen.aot.graalvm.ReflectionConfigGenerator 24 | // info.picocli:picocli-codegen:4.6.3') 25 | // Then match err contains "Missing required parameter: ''" 26 | @Test 27 | void testJavaLaunchGAV() { 28 | assertThat(shell( 29 | "jbang --main picocli.codegen.aot.graalvm.ReflectionConfigGenerator info.picocli:picocli-codegen:4.6.3")) 30 | .errContains( 31 | "Missing required parameter: ''"); 32 | } 33 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/JavaVersionIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class JavaVersionIT extends BaseIT { 8 | 9 | // Feature: java version control 10 | 11 | // Scenario: java run non existent //java 12 | // When command('jbang --verbose java4321.java') 13 | // Then match err contains "JDK version is not available for installation: 4321" 14 | @Test 15 | public void testNonExistentJavaVersion() { 16 | assertThat(shell("jbang --verbose java4321.java")) 17 | .errContains( 18 | "No suitable JDK was found for requested version: 4321"); 19 | } 20 | 21 | // Scenario: java run with explicit java 8 22 | // When command('jbang --verbose --java 8 java4321.java') 23 | // Then match err !contains "JDK version is not available for installation: 24 | // 4321" 25 | @Test 26 | public void testExplicitJava8() { 27 | assertThat(shell("jbang --verbose --java 8 java4321.java")) 28 | .errNotContains( 29 | "JDK version is not available for installation: 4321"); 30 | } 31 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/MarkdownIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | //TODO: fresh should not be needed. probably due to not running isolated enough. 8 | 9 | public class MarkdownIT extends BaseIT { 10 | 11 | // Feature: markdown 12 | 13 | // Scenario: readme.md 14 | // * command('jbang readme.md') 15 | // * match err contains "[jbang] Resolving dependencies..." 16 | // * match out contains "You have no arguments!" 17 | @Test 18 | public void testReadmeMd() { 19 | assertThat(shell("jbang --fresh readme.md")) 20 | .succeeded() 21 | .errContains("[jbang] Resolving dependencies...") 22 | .outContains("You have no arguments!"); 23 | } 24 | 25 | // Scenario: readme.md with args 26 | // * command('jbang readme.md wonderful world') 27 | // * match err contains "[jbang] Resolving dependencies..." 28 | // * match out contains "You have 2 arguments! First is wonderful\n" 29 | @Test 30 | public void testReadmeMdWithArgs() { 31 | 32 | assertThat(shell("jbang --fresh readme.md wonderful world")) 33 | .succeeded() 34 | .errContains("[jbang] Resolving dependencies...") 35 | .outContains( 36 | "You have 2 arguments! First is wonderful"); 37 | } 38 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/QuotingWinIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | import static java.lang.System.lineSeparator; 5 | 6 | import java.util.Collections; 7 | 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.condition.EnabledOnOs; 10 | import org.junit.jupiter.api.condition.OS; 11 | 12 | @EnabledOnOs(OS.WINDOWS) 13 | public class QuotingWinIT extends BaseIT { 14 | 15 | // Scenario: check quotes are kept when wrapped with quotes 16 | // When command('jbang echo.java "foo *"') 17 | // Then match out == "0:foo *\n" 18 | @Test 19 | public void shouldKeepQuotesWhenWrappedWithQuotes() { 20 | assertThat(shell("jbang echo.java \"foo *\"")).outIsExactly("0:foo *" + lineSeparator()); 21 | } 22 | 23 | // Scenario: check expansion does happen 24 | // When command('jbang echo.java foo *') 25 | // Then match out contains "0:foo\n1:" 26 | @Test 27 | public void shouldExpand() { 28 | assertThat(shell("jbang echo.java foo *")).outContains("0:foo" + lineSeparator() + "1:"); 29 | } 30 | 31 | // Scenario: check special characters on command line work 32 | // When command('jbang echo.java " ~!@#$%^&*()-+\\:;\'`<>?/,.{}[]""') 33 | // Then match out == "0: ~!@#$%^&*()-+\\:;'`<>?/,.{}[]\"\n" 34 | @Test 35 | public void shouldHandleSpecialCharacters() { 36 | assertThat(shell("jbang echo.java \" ~!@#$%^&*()-+\\:;\'`<>?/,.{}[]\"")).outIsExactly( 37 | "0: ~!@#$%^&*()-+\\:;'`<>?/,.{}[]" + lineSeparator()); 38 | } 39 | 40 | // Scenario: check spaces in JBANG_DIR path work (Issue #171) 41 | // When command('jbang echo.java "foo *"', { JBANG_DIR: scratch + '\\jbang dir 42 | // test' }) 43 | // Then match out == "0:foo *\n" 44 | @Test 45 | public void shouldHandleSpacesInJBANG_DIRPath() { 46 | assertThat(shell( 47 | Collections.singletonMap("JBANG_DIR", scratch().resolve("jbang dir test").toString()), 48 | "jbang echo.java \"foo *\"")) 49 | .outIsExactly("0:foo *" + lineSeparator()); 50 | } 51 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/RunKotlin.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class RunKotlin extends BaseIT { 8 | 9 | // Feature: run-kotlin 10 | 11 | // Scenario: should not fail to run kotlin 12 | // * command('jbang runkotlin.kt') 13 | // * match out contains 'SUCCESS!' 14 | // * match exit == 0 15 | @Test 16 | public void shouldRunKotlin() { 17 | assertThat(shell("jbang runkotlin.kt")).outContains("SUCCESS!").exitedWith(0); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/RunNix.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.condition.DisabledOnOs; 7 | import org.junit.jupiter.api.condition.OS; 8 | 9 | @DisabledOnOs(OS.WINDOWS) 10 | public class RunNix extends BaseIT { 11 | 12 | // Feature: run on non-windows 13 | 14 | // Background: 15 | // * if (windows) karate.abort() 16 | 17 | // Scenario: as code option 2 18 | // * command('jbang --code "$(cat helloworld.java)" jbangtest') 19 | // * match err == "[jbang] Building jar for helloworld.java...\n" 20 | // * match out == "Hello jbangtest\n" 21 | @Test 22 | public void shouldRunAsCodeOption2() { 23 | assertThat(shell("jbang --code \"$(cat helloworld.java)\" jbangtest")) 24 | .errContains( 25 | "[jbang] Building jar for helloworld.java...\n") 26 | .outIsExactly("Hello jbangtest\n"); 27 | } 28 | 29 | // Scenario: as code option 3 30 | // * command('jbang "--code=$(cat helloworld.java)" jbangtest') 31 | // * match err == "[jbang] Building jar for helloworld.java...\n" 32 | // * match out == "Hello jbangtest\n" 33 | @Test 34 | public void shouldRunAsCodeOption3() { 35 | // TODO: fresh should not be needed. isolation issue. 36 | assertThat(shell("jbang --fresh \"--code=$(cat helloworld.java)\" jbangtest")) 37 | .errIsExactly( 38 | "[jbang] Building jar for helloworld.java...\n") 39 | .outIsExactly( 40 | "Hello jbangtest\n"); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/ShellEnvIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class ShellEnvIT extends BaseIT { 8 | 9 | // Feature: env variables 10 | 11 | // Scenario: JBANG_RUNTIME_SHELL available 12 | // When command('jbang env@jbangdev JBANG') 13 | // Then match out contains "JBANG_RUNTIME_SHELL" 14 | @Test 15 | public void testRuntimeShellAvailable() { 16 | assertThat(shell("jbang env@jbangdev JBANG")) 17 | .succeeded() 18 | .outContains("JBANG_RUNTIME_SHELL"); 19 | } 20 | 21 | // Scenario: JBANG_STDIN_NOTTY available 22 | // When command('jbang env@jbangdev JBANG') 23 | // Then match out contains "JBANG_STDIN_NOTTY" 24 | @Test 25 | public void testStdinNottyAvailable() { 26 | assertThat(shell("jbang env@jbangdev JBANG")) 27 | .succeeded() 28 | .outContains("JBANG_STDIN_NOTTY"); 29 | } 30 | 31 | // Scenario: JBANG_LAUNCH_CMD available 32 | // When command('jbang env@jbangdev JBANG') 33 | // Then match out contains "JBANG_LAUNCH_CMD" 34 | @Test 35 | public void testLaunchCmdAvailable() { 36 | assertThat(shell("jbang env@jbangdev JBANG")) 37 | .succeeded() 38 | .outContains("JBANG_LAUNCH_CMD"); 39 | } 40 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/TemplateIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class TemplateIT extends BaseIT { 8 | 9 | // Scenario: Removing built-in template 10 | // When command('jbang template remove hello') 11 | // * match exit == 0 12 | // * match err contains "Cannot remove template hello from built-in catalog" 13 | @Test 14 | public void shouldRemoveBuiltInTemplate() { 15 | assertThat(shell("jbang template remove hello")).succeeded() 16 | .errContains( 17 | "Cannot remove template hello from built-in catalog"); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/it/java/dev/jbang/it/VersionIT.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.it; 2 | 3 | import static dev.jbang.it.CommandResultAssert.assertThat; 4 | import static java.lang.System.lineSeparator; 5 | 6 | import java.util.regex.Pattern; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class VersionIT extends BaseIT { 11 | 12 | // Feature: version command 13 | 14 | // Scenario: version 15 | // * command('jbang version') 16 | // * match out == '#regex (?s)\\d+\\.\\d+\\.\\d+(\\.\\d+)?.*' 17 | // * match err == '' 18 | // * match exit == 0 19 | @Test 20 | public void shouldVersion() { 21 | assertThat(shell("jbang version")).succeeded() 22 | .outMatches(Pattern.compile( 23 | "(?s)\\d+\\.\\d+\\.\\d+(\\.\\d+)?" + lineSeparator())) 24 | .errEquals(""); 25 | } 26 | 27 | // Scenario: verbose version 28 | // * command('jbang --verbose version') 29 | // * match out == '#regex (?s)\\d+\\.\\d+\\.\\d+(\\.\\d+)?.*' 30 | // * match err contains 'Repository' 31 | // * match exit == 0 32 | @Test 33 | public void shouldVerboseVersion() { 34 | assertThat(shell("jbang --verbose version")).succeeded() 35 | .outMatches(Pattern.compile( 36 | "(?s)\\d+\\.\\d+\\.\\d+(\\.\\d+)?" + lineSeparator())) 37 | .errContains("Repository"); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/it/resources/allure.properties: -------------------------------------------------------------------------------- 1 | allure.results.directory=build/allure-results 2 | allure.label.tag = integration-test 3 | allure.label.layer = integration -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/brew/README.md.tpl: -------------------------------------------------------------------------------- 1 | # Homebrew Formulae 2 | 3 | ## How do I install these formulae? 4 | `brew install {{repoOwner}}/tap/{{distributionName}}` 5 | 6 | Or `brew tap {{repoOwner}}/{{distributionName}}` and then `brew install {{distributionName}}`. 7 | 8 | Or install via URL (which will not receive updates): 9 | 10 | ``` 11 | brew install https://raw.githubusercontent.com/{{repoOwner}}/homebrew-tap/master/Formula/{{distributionName}}.rb 12 | ``` 13 | 14 | ## Documentation 15 | `brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh). 16 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/brew/formula.rb.tpl: -------------------------------------------------------------------------------- 1 | class {{brewFormulaName}} < Formula 2 | desc "{{projectDescription}}" 3 | homepage "{{projectWebsite}}" 4 | version "{{projectVersion}}" 5 | url "{{distributionUrl}}" 6 | sha256 "{{distributionSha256}}" 7 | license "{{projectLicense}}" 8 | 9 | {{#brewDependencies}} 10 | depends_on {{.}} 11 | {{/brewDependencies}} 12 | 13 | def install 14 | libexec.install Dir["*"] 15 | inreplace "#{libexec}/bin/{{distributionExecutable}}", /^abs_jbang_dir=.*/, "abs_jbang_dir=#{libexec}/bin" 16 | bin.install_symlink "#{libexec}/bin/{{distributionExecutable}}" 17 | end 18 | 19 | test do 20 | system "#{bin}/{{distributionExecutable}}", "init", "-t", "cli", "hello.java" 21 | system "#{bin}/{{distributionExecutable}}", "hello.java", "Homebrew!" 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/docker/Dockerfile.tpl: -------------------------------------------------------------------------------- 1 | FROM {{dockerBaseImage}} 2 | 3 | {{#dockerLabels}} 4 | LABEL {{.}} 5 | {{/dockerLabels}} 6 | 7 | {{#dockerPreCommands}} 8 | {{.}} 9 | {{/dockerPreCommands}} 10 | 11 | COPY assembly/* / 12 | 13 | ## mkdir of .userPrefs is to fix https://github.com/jbangdev/jbang/issues/1831 14 | RUN jar xf {{distributionArtifactFileName}}{{distributionArtifactFileExtension}} && \ 15 | rm {{distributionArtifactFileName}}{{distributionArtifactFileExtension}} && \ 16 | mv jbang-* jbang && \ 17 | chmod +x jbang/bin/jbang && \ 18 | mkdir -p $HOME/.java/.userPrefs 19 | 20 | 21 | {{#dockerPostCommands}} 22 | {{.}} 23 | {{/dockerPostCommands}} 24 | 25 | ENV PATH="${PATH}:/{{distributionArtifactName}}/bin" 26 | 27 | ADD ./entrypoint /bin/entrypoint 28 | 29 | ENV SCRIPTS_HOME /scripts 30 | ENV JBANG_VERSION {{projectVersion}} 31 | ENV JBANG_PATH=/jbang/bin 32 | 33 | VOLUME /scripts 34 | 35 | ENV PATH="${PATH}:/jbang/bin" 36 | 37 | ## github action does not allow writing to $HOME thus routing this elsewhere 38 | ENV JBANG_DIR="/jbang/.jbang" 39 | 40 | ENTRYPOINT ["entrypoint"] 41 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/docker/action.yml.tpl: -------------------------------------------------------------------------------- 1 | name: 'Java Scripting w/jbang' 2 | description: 'Run Java as scripts with https://jbang.dev from your GitHub repo' 3 | branding: 4 | icon: hash 5 | color: red 6 | inputs: 7 | jbangargs: 8 | description: 'Arguments for jbang' 9 | required: false 10 | script: 11 | description: 'Script file to run' 12 | required: true 13 | scriptargs: 14 | description: 'arguments to pass on to the script' 15 | required: false 16 | trust: 17 | description: "if present will be added to trust before running jbang" 18 | required: false 19 | runs: 20 | using: 'docker' 21 | image: 'docker://ghcr.io/jbangdev/jbang-action:{{projectVersion}}' 22 | 23 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/docker/container-structure-test.yaml: -------------------------------------------------------------------------------- 1 | schemaVersion: "2.0.0" 2 | 3 | # check that jbang is in the correct location 4 | fileExistenceTests: 5 | - name: "jbang installation" 6 | path: '/jbang/bin/jbang' 7 | shouldExist: true 8 | 9 | commandTests: 10 | - name: "does basic jbang work" 11 | command: "/jbang/bin/jbang" 12 | expectedError: 13 | - "jbang is a tool for building and running" 14 | - "Website: https" 15 | - name: "JBANG_VERSION has a version number" 16 | command: "echo" 17 | args: ["jb $JBANG_VERSION"] 18 | expectedOutput: ["jb \\d+.\\d+\\d+"] 19 | - name: "hello world via url" 20 | command: "entrypoint" 21 | args: 22 | - "https://github.com/jbangdev/jbang/blob/HEAD/itests/helloworld.java" 23 | expectedOutput: 24 | - "Hello World" 25 | - name: "Does trust work" 26 | envVars: 27 | - key: INPUT_TRUST 28 | value: https://github.com/jruby 29 | command: "entrypoint" 30 | expectedError: 31 | - ".*(Trusting permanently:).*" 32 | - ".*(https://github.com/jruby).*" 33 | - name: "Does multiple arguments work" 34 | envVars: 35 | - key: INPUT_SCRIPT 36 | value: hello@jbangdev 37 | - key: INPUT_SCRIPTARGS 38 | value: Hello There 39 | command: "entrypoint" 40 | expectedOutput: 41 | - "Hello Hello" 42 | - "Hello There" 43 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/docker/entrypoint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # In OpenShift, containers are run as a random high number uid 4 | # that doesn't exist in /etc/passwd 5 | if [ `id -u` -ge 500 ] || [ -z "${CURRENT_UID}" ]; then 6 | 7 | cat << EOF > /tmp/passwd 8 | root:x:0:0:root:/root:/bin/bash 9 | jbang:x:`id -u`:`id -g`:,,,:/scripts:/bin/bash 10 | EOF 11 | 12 | cat /tmp/passwd > /etc/passwd 13 | rm /tmp/passwd 14 | fi 15 | 16 | if [[ ! -z "$INPUT_TRUST" ]]; then 17 | $JBANG_PATH/jbang trust add $INPUT_TRUST 18 | fi 19 | 20 | echo jbang $INPUT_JBANGARGS $INPUT_SCRIPT $INPUT_ARGS "${@}" 21 | exec $JBANG_PATH/jbang $INPUT_JBANGARGS $INPUT_SCRIPT $INPUT_SCRIPTARGS "${@}" 22 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/snap/.gitignore: -------------------------------------------------------------------------------- 1 | *.snap 2 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/snap/README.md.tpl: -------------------------------------------------------------------------------- 1 | # Snap repo for {{distributionName}} 2 | 3 | [![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-white.svg)](https://snapcraft.io/{{distributionName}}) 4 | 5 | Snap configuration for {{projectNameCapitalized}} 6 | 7 | Builds with [https://snapcraft.io/{{distributionName}}/builds](https://snapcraft.io/{{distributionName}}/builds) 8 | -------------------------------------------------------------------------------- /src/jreleaser/distributions/jbang/snap/snap/snapcraft.yaml.tpl: -------------------------------------------------------------------------------- 1 | name: {{distributionName}} 2 | version: {{projectVersion}} 3 | summary: {{projectDescription}} 4 | description: {{projectLongDescription}} 5 | 6 | grade: {{snapGrade}} 7 | confinement: {{snapConfinement}} 8 | base: {{snapBase}} 9 | type: app 10 | 11 | apps: 12 | {{distributionExecutable}}: 13 | command: bin/{{distributionExecutable}} 14 | 15 | parts: 16 | {{distributionExecutable}}: 17 | plugin: dump 18 | source: {{distributionUrl}} 19 | source-checksum: sha256/{{distributionChecksumSha256}} 20 | stage-packages: 21 | - curl 22 | -------------------------------------------------------------------------------- /src/jreleaser/templates/article/blogpost.adoc: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | # {{projectNameCapitalized}} {{projectEffectiveVersion}} released 4 | :page-tags: [release] 5 | :page-tagline: {{projectEffectiveVersion}} is the latest release. 6 | :page-author: maxandersen 7 | 8 | {{projectNameCapitalized}} {{projectEffectiveVersion}} have been released with a new round of bugfixes and documentation improvements. 9 | 10 | == Full changelog 11 | 12 | You can see {{releaseNotesUrl}}[the full changelog of {{projectEffectiveVersion}} on GitHub]. -------------------------------------------------------------------------------- /src/main/assembly/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | dist 4 | 5 | 6 | zip 7 | 8 | 9 | 10 | 11 | 12 | 16 | false 17 | lib 18 | false 19 | 20 | 21 | 22 | 23 | 27 | 28 | ${project.build.scriptSourceDirectory} 29 | 30 | 31 | jbang 32 | 33 | 34 | 38 | 39 | ${project.build.directory} 40 | 41 | 42 | *.jar 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/Cache.java: -------------------------------------------------------------------------------- 1 | package dev.jbang; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | 7 | import dev.jbang.cli.ExitException; 8 | import dev.jbang.devkitman.Jdk; 9 | import dev.jbang.devkitman.JdkManager; 10 | import dev.jbang.util.JavaUtil; 11 | import dev.jbang.util.Util; 12 | 13 | public class Cache { 14 | 15 | public enum CacheClass { 16 | urls, jars, jdks, kotlincs, groovycs, projects, scripts, stdins, deps 17 | } 18 | 19 | static void setupCache(Path dir) { 20 | // create cache dir if it does not yet exist 21 | dir.toFile().mkdirs(); 22 | } 23 | 24 | public static void clearCache(CacheClass... classes) { 25 | for (CacheClass cc : classes) { 26 | Util.infoMsg("Clearing cache for " + cc.name()); 27 | JdkManager jdkMan = JavaUtil.defaultJdkManager(); 28 | if (cc == CacheClass.jdks && Util.isWindows() && jdkMan.isCurrentJdkManaged()) { 29 | // We're running using a managed JDK on Windows so we can't just delete the 30 | // entire folder! 31 | for (Jdk jdk : jdkMan.listInstalledJdks()) { 32 | jdkMan.uninstallJdk(jdk); 33 | } 34 | } 35 | if (cc == CacheClass.deps) { 36 | try { 37 | if (Settings.getCacheDependencyFile().toFile().exists()) { 38 | Util.verboseMsg("Deleting file " + Settings.getCacheDependencyFile()); 39 | Files.deleteIfExists(Settings.getCacheDependencyFile().toAbsolutePath()); 40 | } 41 | } catch (IOException io) { 42 | throw new ExitException(-1, 43 | "Could not delete dependency cache " + Settings.getCacheDependencyFile().toString(), io); 44 | } 45 | } else { 46 | Util.deletePath(Settings.getCacheDir(cc), true); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/catalog/CatalogItem.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.catalog; 2 | 3 | import java.nio.file.Paths; 4 | 5 | import dev.jbang.util.Util; 6 | 7 | abstract class CatalogItem { 8 | public transient Catalog catalog; 9 | 10 | public CatalogItem(Catalog catalog) { 11 | this.catalog = catalog; 12 | } 13 | 14 | /** 15 | * This method returns the given scriptRef with all contextual modifiers like 16 | * baseRefs and current working directories applied. 17 | */ 18 | public String resolve(String scriptRef) { 19 | String ref = scriptRef; 20 | if (!Util.isAbsoluteRef(ref)) { 21 | String base = catalog.getScriptBase(); 22 | if (Util.isRemoteRef(base) || !Util.isValidPath(base)) { 23 | ref = base + "/" + ref; 24 | } else { 25 | ref = Paths.get(base).resolve(ref).toString(); 26 | } 27 | } 28 | return ref; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/catalog/TemplateProperty.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.catalog; 2 | 3 | import java.util.Objects; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | /** 8 | * Class representing a property in the JBang catalog templates. 9 | */ 10 | public class TemplateProperty { 11 | 12 | private String description; 13 | @SerializedName(value = "default") 14 | private String defaultValue; 15 | 16 | public TemplateProperty(String description, String defaultValue) { 17 | this.description = description; 18 | this.defaultValue = defaultValue; 19 | } 20 | 21 | public String getDefaultValue() { 22 | return defaultValue; 23 | } 24 | 25 | public String getDescription() { 26 | return description; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) 32 | return true; 33 | if (o == null || getClass() != o.getClass()) 34 | return false; 35 | TemplateProperty that = (TemplateProperty) o; 36 | return Objects.equals(description, that.description) && Objects.equals(defaultValue, that.defaultValue); 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | return Objects.hash(description, defaultValue); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "TemplateProperty{" + 47 | "description='" + description + '\'' + 48 | ", defaultValue='" + defaultValue + '\'' + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/BaseBuildCommand.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.io.FileDescriptor; 4 | import java.io.FileOutputStream; 5 | import java.io.PrintStream; 6 | import java.nio.file.Path; 7 | 8 | import dev.jbang.source.*; 9 | 10 | import picocli.CommandLine; 11 | 12 | public abstract class BaseBuildCommand extends BaseCommand { 13 | 14 | @CommandLine.Mixin 15 | ScriptMixin scriptMixin; 16 | 17 | @CommandLine.Mixin 18 | BuildMixin buildMixin; 19 | 20 | @CommandLine.Mixin 21 | DependencyInfoMixin dependencyInfoMixin; 22 | 23 | @CommandLine.Mixin 24 | NativeMixin nativeMixin; 25 | 26 | @CommandLine.Option(names = { 27 | "--build-dir" }, description = "Use given directory for build results") 28 | Path buildDir; 29 | 30 | @CommandLine.Option(names = { "--enable-preview" }, description = "Activate Java preview features") 31 | Boolean enablePreviewRequested; 32 | 33 | PrintStream out = new PrintStream(new FileOutputStream(FileDescriptor.out)); 34 | 35 | protected ProjectBuilder createBaseProjectBuilder() { 36 | return Project 37 | .builder() 38 | .setProperties(dependencyInfoMixin.getProperties()) 39 | .additionalDependencies(dependencyInfoMixin.getDependencies()) 40 | .additionalRepositories(dependencyInfoMixin.getRepositories()) 41 | .additionalClasspaths(dependencyInfoMixin.getClasspaths()) 42 | .additionalSources(scriptMixin.sources) 43 | .additionalResources(scriptMixin.resources) 44 | .forceType(scriptMixin.forceType) 45 | .catalog(scriptMixin.catalog) 46 | .javaVersion(buildMixin.javaVersion) 47 | .moduleName(buildMixin.module) 48 | .compileOptions(buildMixin.compileOptions) 49 | .manifestOptions(buildMixin.manifestOptions) 50 | .nativeImage(nativeMixin.nativeImage) 51 | .nativeOptions(nativeMixin.nativeOptions) 52 | .integrations(buildMixin.integrations) 53 | .enablePreview(enablePreviewRequested) 54 | .jdkManager(buildMixin.jdkProvidersMixin.getJdkManager()); 55 | 56 | // NB: Do not put `.mainClass(buildMixin.main)` here 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/Build.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.io.IOException; 4 | 5 | import dev.jbang.source.BuildContext; 6 | import dev.jbang.source.Project; 7 | import dev.jbang.source.ProjectBuilder; 8 | 9 | import picocli.CommandLine.Command; 10 | 11 | @Command(name = "build", description = "Compiles and stores script in the cache.") 12 | public class Build extends BaseBuildCommand { 13 | 14 | @Override 15 | public Integer doCall() throws IOException { 16 | scriptMixin.validate(); 17 | 18 | ProjectBuilder pb = createProjectBuilderForBuild(); 19 | Project prj = pb.build(scriptMixin.scriptOrFile); 20 | Project.codeBuilder(BuildContext.forProject(prj, buildDir)).build(); 21 | 22 | return EXIT_OK; 23 | } 24 | 25 | ProjectBuilder createProjectBuilderForBuild() { 26 | return createBaseProjectBuilder().mainClass(buildMixin.main); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/CommaSeparatedConverter.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import picocli.CommandLine.ITypeConverter; 7 | 8 | public class CommaSeparatedConverter implements ITypeConverter> { 9 | @Override 10 | public List convert(final String input) throws Exception { 11 | return Arrays.asList(input.split(",")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/Completion.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintStream; 5 | 6 | import picocli.AutoComplete; 7 | import picocli.CommandLine; 8 | 9 | @CommandLine.Command(name = "completion", description = "Output auto-completion script for bash/zsh.\nUsage: source <(jbang completion)") 10 | public class Completion extends BaseCommand { 11 | 12 | @Override 13 | public Integer doCall() throws IOException { 14 | return completion(); 15 | } 16 | 17 | public int completion() throws IOException { 18 | String script = AutoComplete.bash( 19 | spec.parent().name(), 20 | spec.parent().commandLine()); 21 | // not PrintWriter.println: scripts with Windows line separators fail in strange 22 | // ways! 23 | 24 | PrintStream out = System.out; 25 | out.print(script); 26 | out.print('\n'); 27 | out.flush(); 28 | return EXIT_OK; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/DeprecatedMessageHandler.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.io.PrintWriter; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import picocli.CommandLine; 8 | import picocli.CommandLine.UnmatchedArgumentException; 9 | 10 | public class DeprecatedMessageHandler implements CommandLine.IParameterExceptionHandler { 11 | private final CommandLine.IParameterExceptionHandler delegate; 12 | 13 | public DeprecatedMessageHandler(CommandLine.IParameterExceptionHandler parameterExceptionHandler) { 14 | this.delegate = parameterExceptionHandler; 15 | } 16 | 17 | static Map oldFlags = new HashMap() { 18 | { 19 | put("--alias", "jbang alias --help"); 20 | put("--init", "jbang init --help"); 21 | put("--edit", "jbang edit --help"); 22 | put("--edit-live", "jbang edit --help"); 23 | put("--trust", "jbang trust --help"); 24 | } 25 | }; 26 | 27 | @Override 28 | public int handleParseException(CommandLine.ParameterException ex, String[] args) throws Exception { 29 | 30 | if (ex instanceof UnmatchedArgumentException) { 31 | CommandLine cmd = ex.getCommandLine(); 32 | PrintWriter writer = cmd.getErr(); 33 | 34 | UnmatchedArgumentException uae = (UnmatchedArgumentException) ex; 35 | String s = uae.getUnmatched().get(0); 36 | if (s.contains("=")) { 37 | s = s.substring(0, s.indexOf("=")); 38 | } 39 | 40 | if (oldFlags.containsKey(s)) { 41 | writer.printf("%s is a deprecated and now removed flag. See " + oldFlags.get(s) 42 | + " for more details on its replacement.\n", s); 43 | } 44 | } 45 | return delegate.handleParseException(ex, args); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/ExitException.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | /** 4 | * Used when wanting to exit app from a command. 5 | */ 6 | public class ExitException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | private final int status; 11 | 12 | public ExitException(int status) { 13 | this.status = status; 14 | } 15 | 16 | public ExitException(int status, Throwable cause) { 17 | super(cause); 18 | this.status = status; 19 | } 20 | 21 | public ExitException(int status, String message, Throwable cause) { 22 | super(message, cause); 23 | this.status = status; 24 | } 25 | 26 | public ExitException(int status, String s) { 27 | this(status, s, null); 28 | } 29 | 30 | public int getStatus() { 31 | return status; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/ExportMixin.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.nio.file.Path; 4 | import java.nio.file.Paths; 5 | 6 | import dev.jbang.catalog.CatalogUtil; 7 | import dev.jbang.util.Util; 8 | 9 | import picocli.CommandLine; 10 | 11 | public class ExportMixin { 12 | 13 | @CommandLine.Mixin 14 | ScriptMixin scriptMixin; 15 | 16 | @CommandLine.Mixin 17 | BuildMixin buildMixin; 18 | 19 | @CommandLine.Mixin 20 | DependencyInfoMixin dependencyInfoMixin; 21 | 22 | @CommandLine.Option(names = { "-O", 23 | "--output" }, description = "The name or path to use for the exported file. If not specified a name will be determined from the original source reference and export flags.") 24 | Path outputFile;// mixins todo above 25 | 26 | @CommandLine.Option(names = { 27 | "--force" }, description = "Force export, i.e. overwrite exported file if already exists") 28 | boolean force; 29 | 30 | @Deprecated 31 | @CommandLine.Option(names = { 32 | "-n", "--native" }, description = "Deprecated: use `jbang export native`", hidden = true) 33 | boolean nativeImage; 34 | 35 | public ExportMixin() { 36 | } 37 | 38 | Path getOutputPath(String postFix) { 39 | // Determine the output file location and name 40 | Path cwd = Util.getCwd(); 41 | Path outputPath; 42 | if (outputFile != null) { 43 | outputPath = outputFile; 44 | } else { 45 | String outName = CatalogUtil.nameFromRef(scriptMixin.scriptOrFile); 46 | outputPath = Paths.get(outName + postFix); 47 | } 48 | outputPath = cwd.resolve(outputPath); 49 | return outputPath; 50 | } 51 | 52 | public void validate() { 53 | scriptMixin.validate(); 54 | if (nativeImage) { 55 | throw new IllegalArgumentException( 56 | "The `-n` and `--native` flags have been removed, use `jbang export native` instead."); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/FormatMixin.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import picocli.CommandLine; 4 | 5 | public class FormatMixin { 6 | 7 | public enum Format { 8 | text, json 9 | } 10 | 11 | @CommandLine.Option(names = { 12 | "--format" }, description = "Specify output format ('text' or 'json')") 13 | protected Format format; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/JdkProvidersMixin.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import dev.jbang.devkitman.JdkManager; 7 | import dev.jbang.util.JavaUtil; 8 | 9 | import picocli.CommandLine; 10 | 11 | public class JdkProvidersMixin { 12 | 13 | @CommandLine.Option(names = { 14 | "--jdk-providers" }, description = "Use the given providers to check for installed JDKs", split = ",", hidden = true) 15 | List jdkProviders; 16 | 17 | private JdkManager jdkMan; 18 | 19 | protected JdkManager getJdkManager() { 20 | if (jdkMan == null) { 21 | jdkMan = JavaUtil.defaultJdkManager(jdkProviders); 22 | } 23 | return jdkMan; 24 | } 25 | 26 | public List opts() { 27 | List opts = new ArrayList<>(); 28 | if (jdkProviders != null) { 29 | for (String p : jdkProviders) { 30 | opts.add("--jdk-providers"); 31 | opts.add(p); 32 | } 33 | } 34 | return opts; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/KeyValueConsumer.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.Stack; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import picocli.CommandLine; 10 | 11 | public class KeyValueConsumer implements CommandLine.IParameterConsumer { 12 | 13 | Pattern p = Pattern.compile("(\\S*?)(=(\\S+))?"); 14 | 15 | @Override 16 | public void consumeParameters(Stack args, CommandLine.Model.ArgSpec argSpec, 17 | CommandLine.Model.CommandSpec commandSpec) { 18 | String arg = args.pop(); 19 | Matcher m = p.matcher(arg); 20 | if (m.matches()) { 21 | Map kv = argSpec.getValue(); 22 | 23 | if (kv == null) { 24 | kv = new LinkedHashMap<>(); 25 | } 26 | 27 | kv.put(m.group(1), m.group(3)); 28 | 29 | argSpec.setValue(kv); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/NativeMixin.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import picocli.CommandLine; 7 | 8 | public class NativeMixin { 9 | @CommandLine.Option(names = { 10 | "-n", "--native" }, description = "Build using native-image") 11 | Boolean nativeImage; 12 | 13 | @CommandLine.Option(names = { "-N", "--native-option" }, description = "Options to pass to the native image tool") 14 | public List nativeOptions; 15 | 16 | public List opts() { 17 | List opts = new ArrayList<>(); 18 | if (Boolean.TRUE.equals(nativeImage)) { 19 | opts.add("--native"); 20 | } 21 | if (nativeOptions != null) { 22 | for (String n : nativeOptions) { 23 | opts.add("-N"); 24 | opts.add(n); 25 | } 26 | } 27 | return opts; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | /** 4 | * Used when something could not be found. 5 | */ 6 | public class ResourceNotFoundException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | String resource; 11 | 12 | public ResourceNotFoundException(String resource, String message, Throwable cause) { 13 | super(message, cause); 14 | this.resource = resource; 15 | } 16 | 17 | public ResourceNotFoundException(String resource, String message) { 18 | this(resource, message, null); 19 | } 20 | 21 | public String getResourceDescription() { 22 | return resource; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/StrictParameterPreprocessor.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.util.Map; 4 | import java.util.Stack; 5 | 6 | import picocli.CommandLine; 7 | 8 | /** 9 | * preprocessor which strictly enforces you have to use a `=` to assign values. 10 | * ie. only `--open=xyz` and `-o=xyz` will be accepted. Useful when you have 11 | * option for which you like default value to be expressed without having it 12 | * pick up additional values on the command line. i.e. `jbang edit --open 13 | * myapp.java` should not treat `myapp.java` as editor to open but instead just 14 | * open the default editor. 15 | */ 16 | public class StrictParameterPreprocessor implements CommandLine.IParameterPreprocessor { 17 | 18 | @Override 19 | public boolean preprocess(Stack args, CommandLine.Model.CommandSpec commandSpec, 20 | CommandLine.Model.ArgSpec argSpec, Map info) { 21 | if (" ".equals(info.get("separator"))) { // parameter was not attached to option 22 | // act as if the user specified fallback value 23 | args.push(((CommandLine.Model.OptionSpec) argSpec).fallbackValue()); 24 | } 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/TemplatePropertyConverter.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import picocli.CommandLine.ITypeConverter; 6 | 7 | /** 8 | * Template property converter that is able to parse the following input: 9 | * 10 | *
    11 | *
  • property-name
  • 12 | *
  • property-name:property-description
  • 13 | *
  • property-name:property-description:default-value
  • 14 | *
  • property-name::default-value
  • 15 | *
16 | * 17 | * Examples: 18 | *
    19 | *
  • test-key
  • 20 | *
  • "test-key:This is a description for the property"
  • 21 | *
  • "test-key:This is a description for the property:2.11"
  • 22 | *
  • "test-key::2.11"
  • 23 | *
24 | * 25 | */ 26 | public class TemplatePropertyConverter implements ITypeConverter { 27 | @Override 28 | public TemplateAdd.TemplatePropertyInput convert(final String input) throws Exception { 29 | String[] propertyParts = input.split(":"); 30 | TemplateAdd.TemplatePropertyInput templatePropertyInput = new TemplateAdd.TemplatePropertyInput(); 31 | if (propertyParts.length > 0 && StringUtils.isNotBlank(propertyParts[0])) { 32 | templatePropertyInput.setKey(propertyParts[0]); 33 | } 34 | if (propertyParts.length > 1 && StringUtils.isNotBlank(propertyParts[1])) { 35 | templatePropertyInput.setDescription(propertyParts[1]); 36 | } 37 | if (propertyParts.length > 2 && StringUtils.isNotBlank(propertyParts[2])) { 38 | templatePropertyInput.setDefaultValue(propertyParts[2]); 39 | } 40 | return templatePropertyInput; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/Version.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | 6 | import dev.jbang.Settings; 7 | import dev.jbang.dependencies.ArtifactResolver; 8 | import dev.jbang.util.Util; 9 | import dev.jbang.util.VersionChecker; 10 | 11 | import picocli.CommandLine; 12 | 13 | @CommandLine.Command(name = "version", description = "Display version info.") 14 | public class Version extends BaseCommand { 15 | 16 | @CommandLine.Option(names = { "--check" }, description = "Check if a new version of jbang is available") 17 | boolean checkForUpdate; 18 | 19 | @CommandLine.Option(names = { "--update" }, description = "Update jbang to the latest version") 20 | boolean update; 21 | 22 | @Override 23 | public Integer doCall() { 24 | if (update) { 25 | if (VersionChecker.updateOrInform(checkForUpdate)) { 26 | try { 27 | AppInstall.installJBang(true); 28 | } catch (IOException e) { 29 | throw new ExitException(EXIT_INTERNAL_ERROR, "Could not install command", e); 30 | } 31 | } 32 | } else if (checkForUpdate) { 33 | System.out.println(Util.getJBangVersion()); 34 | VersionChecker.checkNowAndInform(); 35 | } else { 36 | System.out.println(Util.getJBangVersion()); 37 | } 38 | 39 | if (isVerbose()) { 40 | PrintWriter out = spec.commandLine().getOut(); 41 | out.println("Cache: " + Settings.getCacheDir()); 42 | out.println("Config: " + Settings.getConfigDir()); 43 | out.println("Repository: " + ArtifactResolver.getLocalMavenRepo()); 44 | out.println("Java: " + System.getProperty("java.home") + " [" + System.getProperty("java.version") + "]"); 45 | out.println("OS: " + Util.getOS()); 46 | out.println("Arch: " + Util.getArch()); 47 | out.println("Shell: " + Util.getShell()); 48 | } 49 | 50 | return EXIT_OK; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/cli/VersionProvider.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import dev.jbang.util.Util; 4 | 5 | import picocli.CommandLine; 6 | 7 | public class VersionProvider implements CommandLine.IVersionProvider { 8 | @Override 9 | public String[] getVersion() throws Exception { 10 | return new String[] { Util.getJBangVersion() }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/dependencies/DependencyException.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.dependencies; 2 | 3 | @SuppressWarnings("serial") 4 | public class DependencyException extends RuntimeException { 5 | 6 | public DependencyException(Exception e) { 7 | super(e); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/dependencies/Detector.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.dependencies; 2 | 3 | import java.util.List; 4 | import java.util.Properties; 5 | 6 | public class Detector extends kr.motd.maven.os.Detector { 7 | 8 | public Detector() { 9 | super(); 10 | } 11 | 12 | @Override 13 | protected void log(String message) { 14 | 15 | } 16 | 17 | @Override 18 | protected void logProperty(String name, String value) { 19 | 20 | } 21 | 22 | public void detect(Properties properties, List classiferWithLikes) { 23 | super.detect(properties, classiferWithLikes); 24 | 25 | // "hack" to expose a property that works with javafx mac classifers 26 | String os = properties.getProperty("os.detected.name"); 27 | if (os.equals("osx")) { 28 | os = "mac"; 29 | if ("aarch64".equals(System.getProperty("os.arch"))) { 30 | os = "mac-aarch64"; 31 | } 32 | } else if (os.equals("windows")) { 33 | os = "win"; 34 | } 35 | properties.setProperty("os.detected.jfxname", os); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/dependencies/MavenRepo.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.dependencies; 2 | 3 | import java.util.Objects; 4 | 5 | public class MavenRepo { 6 | 7 | private String id; 8 | private String url; 9 | 10 | public MavenRepo(String id, String url) { 11 | this.setId(id); 12 | this.setUrl(url); 13 | } 14 | 15 | public String getId() { 16 | return id; 17 | } 18 | 19 | public void setId(String id) { 20 | this.id = id; 21 | } 22 | 23 | public String getUrl() { 24 | return url; 25 | } 26 | 27 | public void setUrl(String url) { 28 | this.url = url; 29 | } 30 | 31 | @Override 32 | public boolean equals(Object o) { 33 | if (this == o) 34 | return true; 35 | if (o == null || getClass() != o.getClass()) 36 | return false; 37 | MavenRepo mavenRepo = (MavenRepo) o; 38 | return Objects.equals(id, mavenRepo.id) && Objects.equals(url, mavenRepo.url); 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return Objects.hash(id, url); 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return String.format("%s=%s", id, url); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/Builder.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | import java.io.IOException; 4 | 5 | public interface Builder { 6 | T build() throws IOException; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/CmdGenerator.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | import java.io.IOException; 4 | 5 | public interface CmdGenerator { 6 | String generate() throws IOException; 7 | 8 | static CmdGeneratorBuilder builder(Project project) { 9 | return new CmdGeneratorBuilder(BuildContext.forProject(project)); 10 | } 11 | 12 | static CmdGeneratorBuilder builder(BuildContext ctx) { 13 | return new CmdGeneratorBuilder(ctx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/DirectResourceRef.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | import java.nio.file.Path; 4 | import java.util.Objects; 5 | 6 | import javax.annotation.Nullable; 7 | 8 | public class DirectResourceRef implements ResourceRef { 9 | @Nullable 10 | private final String originalResource; 11 | @Nullable 12 | private final Path file; 13 | 14 | protected DirectResourceRef(@Nullable String ref, @Nullable Path file) { 15 | this.originalResource = ref; 16 | this.file = file; 17 | } 18 | 19 | @Nullable 20 | @Override 21 | public String getOriginalResource() { 22 | return originalResource; 23 | } 24 | 25 | @Nullable 26 | @Override 27 | public Path getFile() { 28 | return file; 29 | } 30 | 31 | @Override 32 | public boolean equals(Object o) { 33 | if (this == o) 34 | return true; 35 | if (o == null || getClass() != o.getClass()) 36 | return false; 37 | DirectResourceRef that = (DirectResourceRef) o; 38 | return Objects.equals(originalResource, that.originalResource) && 39 | Objects.equals(file, that.file); 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return Objects.hash(originalResource, file); 45 | } 46 | 47 | @Override 48 | public int compareTo(ResourceRef o) { 49 | if (o == null) { 50 | return 1; 51 | } 52 | return toString().compareTo(o.toString()); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | if (originalResource != null && file != null) { 58 | if (originalResource.equals(file.toString())) { 59 | return originalResource; 60 | } else { 61 | return originalResource + " (cached as: " + file + ")"; 62 | } 63 | } else { 64 | String res = ""; 65 | if (originalResource != null) { 66 | res += originalResource; 67 | } 68 | if (file != null) { 69 | res += file; 70 | } 71 | return res; 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/KeyValue.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | public class KeyValue { 4 | final String key; 5 | final String value; 6 | 7 | public KeyValue(String key, String value) { 8 | this.key = key; 9 | this.value = value; 10 | } 11 | 12 | public String getKey() { 13 | return key; 14 | } 15 | 16 | public String getValue() { 17 | return value; 18 | } 19 | 20 | public String toManifestString() { 21 | return getKey() + ": " + value; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return getKey() + "=" + getValue() == null ? "" : getValue(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/buildsteps/IntegrationBuildStep.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.buildsteps; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | import java.util.Properties; 6 | 7 | import dev.jbang.source.BuildContext; 8 | import dev.jbang.source.Builder; 9 | import dev.jbang.source.Project; 10 | import dev.jbang.spi.IntegrationManager; 11 | import dev.jbang.spi.IntegrationResult; 12 | 13 | /** 14 | * This class takes a Project and the result of a previous 15 | * "compile" step and runs any integrations that might be found. Those 16 | * integration can make changes to the project that will be used as the input 17 | * for the next build step. 18 | */ 19 | public class IntegrationBuildStep implements Builder { 20 | private final BuildContext ctx; 21 | 22 | public IntegrationBuildStep(BuildContext ctx) { 23 | this.ctx = ctx; 24 | } 25 | 26 | @Override 27 | public IntegrationResult build() throws IOException { 28 | // todo: setting properties to avoid loosing properties in integration call. 29 | Project project = ctx.getProject(); 30 | Properties oldProps = System.getProperties(); 31 | Properties tempProps = new Properties(); 32 | tempProps.putAll(oldProps); 33 | System.setProperties(tempProps); 34 | for (Map.Entry entry : project.getProperties().entrySet()) { 35 | System.setProperty(entry.getKey(), entry.getValue()); 36 | } 37 | try { 38 | IntegrationResult integrationResult = IntegrationManager.runIntegrations(ctx); 39 | 40 | if (project.getMainClass() == null) { // if non-null user forced set main 41 | if (integrationResult.mainClass != null) { 42 | project.setMainClass(integrationResult.mainClass); 43 | } 44 | } 45 | if (integrationResult.javaArgs != null && !integrationResult.javaArgs.isEmpty()) { 46 | // Add integration options to the java options 47 | project.addRuntimeOptions(integrationResult.javaArgs); 48 | } 49 | return integrationResult; 50 | } finally { 51 | System.setProperties(oldProps); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/generators/BaseCmdGenerator.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.generators; 2 | 3 | import java.io.IOException; 4 | import java.util.*; 5 | 6 | import dev.jbang.source.*; 7 | import dev.jbang.util.CommandBuffer; 8 | import dev.jbang.util.Util; 9 | 10 | public abstract class BaseCmdGenerator implements CmdGenerator { 11 | protected final BuildContext ctx; 12 | 13 | protected List arguments = Collections.emptyList(); 14 | protected Map debugString; 15 | protected String flightRecorderString; 16 | 17 | protected Util.Shell shell = Util.getShell(); 18 | 19 | @SuppressWarnings("unchecked") 20 | public T arguments(List arguments) { 21 | this.arguments = arguments != null ? arguments : Collections.emptyList(); 22 | return (T) this; 23 | } 24 | 25 | @SuppressWarnings("unchecked") 26 | public T shell(Util.Shell shell) { 27 | this.shell = shell; 28 | return (T) this; 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | public T debugString(Map debugString) { 33 | this.debugString = debugString != null && !debugString.isEmpty() ? debugString : null; 34 | return (T) this; 35 | } 36 | 37 | @SuppressWarnings("unchecked") 38 | public T flightRecorderString(String flightRecorderString) { 39 | this.flightRecorderString = flightRecorderString != null && !flightRecorderString.isEmpty() 40 | ? flightRecorderString 41 | : null; 42 | return (T) this; 43 | } 44 | 45 | public BaseCmdGenerator(BuildContext ctx) { 46 | this.ctx = ctx; 47 | } 48 | 49 | @Override 50 | public String generate() throws IOException { 51 | List fullArgs = generateCommandLineList(); 52 | return generateCommandLineString(fullArgs); 53 | } 54 | 55 | protected abstract List generateCommandLineList() throws IOException; 56 | 57 | protected String generateCommandLineString(List fullArgs) throws IOException { 58 | CommandBuffer cb = CommandBuffer.of(fullArgs); 59 | return cb.shell(shell).asCommandLine(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/generators/NativeCmdGenerator.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.generators; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import dev.jbang.source.BuildContext; 10 | import dev.jbang.source.CmdGenerator; 11 | import dev.jbang.util.Util; 12 | 13 | public class NativeCmdGenerator extends BaseCmdGenerator { 14 | private final CmdGenerator fallback; 15 | 16 | public NativeCmdGenerator(BuildContext ctx, CmdGenerator fallback) { 17 | super(ctx); 18 | this.fallback = fallback; 19 | } 20 | 21 | @Override 22 | public String generate() throws IOException { 23 | List fullArgs = new ArrayList<>(); 24 | 25 | if (ctx.getProject().enablePreview()) { 26 | fullArgs.add("--enable-preview"); 27 | } 28 | 29 | Path image = ctx.getNativeImageFile(); 30 | if (Files.exists(image)) { 31 | fullArgs.add(image.toString()); 32 | } else { 33 | Util.warnMsg("native built image not found - running in java mode."); 34 | return fallback.generate(); 35 | } 36 | 37 | fullArgs.addAll(arguments); 38 | 39 | return generateCommandLineString(fullArgs); 40 | } 41 | 42 | @Override 43 | protected List generateCommandLineList() throws IOException { 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/resolvers/CombinedResourceResolver.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.resolvers; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.stream.Collectors; 7 | 8 | import javax.annotation.Nonnull; 9 | 10 | import dev.jbang.source.ResourceRef; 11 | import dev.jbang.source.ResourceResolver; 12 | 13 | /** 14 | * A ResourceResolver that, when given a resource string will 15 | * delegate the resolving of that string to a list of resolvers one by one until 16 | * one of them returns a result and that will then be the result of this 17 | * resolver. 18 | */ 19 | public class CombinedResourceResolver implements ResourceResolver { 20 | private final List resolvers; 21 | 22 | public CombinedResourceResolver(ResourceResolver... resolvers) { 23 | this.resolvers = Arrays.asList(resolvers); 24 | } 25 | 26 | @Override 27 | public ResourceRef resolve(String resource, boolean trusted) { 28 | return resolvers.stream() 29 | .map(r -> r.resolve(resource, trusted)) 30 | .filter(Objects::nonNull) 31 | .findFirst() 32 | .orElse(null); 33 | } 34 | 35 | @Nonnull 36 | @Override 37 | public String description() { 38 | return String.format("Chain of [%s]", 39 | resolvers.stream().map(r -> r.description()).collect(Collectors.joining(", "))); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/resolvers/FileResourceResolver.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.resolvers; 2 | 3 | import java.nio.file.Files; 4 | import java.nio.file.InvalidPathException; 5 | import java.nio.file.Path; 6 | 7 | import javax.annotation.Nonnull; 8 | 9 | import dev.jbang.source.ResourceRef; 10 | import dev.jbang.source.ResourceResolver; 11 | import dev.jbang.util.Util; 12 | 13 | /** 14 | * A ResourceResolver that, when given a resource string which 15 | * looks like a path to a file on the local file system, will return a reference 16 | * to that file. 17 | */ 18 | public class FileResourceResolver implements ResourceResolver { 19 | 20 | @Nonnull 21 | @Override 22 | public String description() { 23 | return "File Resource resolver"; 24 | } 25 | 26 | @Override 27 | public ResourceRef resolve(String resource) { 28 | ResourceRef result = null; 29 | 30 | Path probe = null; 31 | try { 32 | probe = Util.getCwd().resolve(resource).normalize(); 33 | } catch (InvalidPathException e) { 34 | // Ignore 35 | } 36 | 37 | if (probe != null && Files.isReadable(probe)) { 38 | result = ResourceRef.forResolvedResource(resource, probe); 39 | } 40 | 41 | return result; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/resolvers/GavResourceResolver.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.resolvers; 2 | 3 | import java.nio.file.Path; 4 | import java.util.function.Function; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | import dev.jbang.dependencies.DependencyUtil; 9 | import dev.jbang.dependencies.ModularClassPath; 10 | import dev.jbang.source.ResourceRef; 11 | import dev.jbang.source.ResourceResolver; 12 | 13 | /** 14 | * A ResourceResolver that, when given a resource string which 15 | * looks like a Maven GAV, will try to resolve that dependency and return a 16 | * reference to the downloaded artifact JAR. 17 | */ 18 | public class GavResourceResolver implements ResourceResolver { 19 | private final Function depResolver; 20 | 21 | public GavResourceResolver(Function depResolver) { 22 | this.depResolver = depResolver; 23 | } 24 | 25 | @Nonnull 26 | @Override 27 | public String description() { 28 | return "Maven GAV"; 29 | } 30 | 31 | @Override 32 | public ResourceRef resolve(String resource) { 33 | ResourceRef result = null; 34 | 35 | if (DependencyUtil.looksLikeAGav(resource)) { 36 | // todo honor offline 37 | ModularClassPath mcp = depResolver.apply(resource); 38 | // We possibly get a whole bunch of artifacts but we're only interested in the 39 | // one we asked for, which we assume is always the first one in the list 40 | // (hopefully we're right). 41 | Path file = mcp.getArtifacts().get(0).getFile(); 42 | result = ResourceRef.forResolvedResource(resource, file); 43 | } 44 | 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/resolvers/LazyResourceResolver.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.resolvers; 2 | 3 | import javax.annotation.Nonnull; 4 | 5 | import dev.jbang.source.ResourceRef; 6 | import dev.jbang.source.ResourceResolver; 7 | 8 | /** 9 | * A {@code LazyResourceResolver} is a wrapper around an existing 10 | * {@link ResourceResolver} that enables lazy resolution of resources. This 11 | * means that resource resolution is deferred until access to the resource 12 | * content is explicitly requested, at which point the resource will be handed 13 | * over to the wrapped resolver for resolution. 14 | */ 15 | public class LazyResourceResolver implements ResourceResolver { 16 | private final ResourceResolver wrappedResolver; 17 | 18 | public LazyResourceResolver(ResourceResolver wrappedResolver) { 19 | this.wrappedResolver = wrappedResolver; 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public String description() { 25 | return "Lazy Resource resolver"; 26 | } 27 | 28 | @Override 29 | public ResourceRef resolve(String resource, boolean trusted) { 30 | return ResourceRef.lazy(wrappedResolver, resource); 31 | } 32 | 33 | public static ResourceResolver lazy(ResourceResolver resolver) { 34 | if (resolver instanceof LazyResourceResolver) { 35 | return resolver; 36 | } 37 | return new LazyResourceResolver(resolver); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/source/sources/JshSource.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source.sources; 2 | 3 | import java.util.function.Function; 4 | 5 | import javax.annotation.Nonnull; 6 | 7 | import dev.jbang.source.*; 8 | 9 | public class JshSource extends JavaSource { 10 | public JshSource(ResourceRef script, Function replaceProperties) { 11 | super(script, replaceProperties); 12 | } 13 | 14 | protected JshSource(ResourceRef ref, String script, Function replaceProperties) { 15 | super(ref, script, replaceProperties); 16 | } 17 | 18 | @Override 19 | public @Nonnull Type getType() { 20 | return Type.jshell; 21 | } 22 | 23 | @Override 24 | public Builder getBuilder(BuildContext ctx) { 25 | return () -> CmdGenerator.builder(ctx); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/spi/IntegrationInput.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.spi; 2 | 3 | import java.nio.file.Path; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | public class IntegrationInput { 10 | @SerializedName(value = "integration") 11 | public final String integrationClassName; 12 | public final Path source; 13 | public final Path classes; 14 | public final Path pom; 15 | public final Map repositories; 16 | public final Map dependencies; 17 | public final List comments; 18 | @SerializedName(value = "native") 19 | public final boolean nativeRequested; 20 | public final boolean verbose; 21 | 22 | public IntegrationInput(String integrationClassName, Path source, Path classes, Path pom, 23 | Map repositories, Map dependencies, List comments, 24 | boolean nativeRequested, boolean verbose) { 25 | this.integrationClassName = integrationClassName; 26 | this.source = source; 27 | this.classes = classes; 28 | this.pom = pom; 29 | this.repositories = repositories; 30 | this.dependencies = dependencies; 31 | this.comments = comments; 32 | this.nativeRequested = nativeRequested; 33 | this.verbose = verbose; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/spi/IntegrationResult.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.spi; 2 | 3 | import java.nio.file.Path; 4 | import java.util.List; 5 | 6 | public class IntegrationResult { 7 | 8 | public final Path nativeImagePath; 9 | public final String mainClass; 10 | public final List javaArgs; 11 | 12 | public IntegrationResult(Path nativeImagePath, String mainClass, List javaArgs) { 13 | this.nativeImagePath = nativeImagePath; 14 | this.mainClass = mainClass; 15 | this.javaArgs = javaArgs; 16 | } 17 | 18 | public IntegrationResult merged(IntegrationResult ir) { 19 | if (ir.nativeImagePath == null && ir.mainClass == null && ir.javaArgs == null) { 20 | return this; 21 | } else if (nativeImagePath == null && mainClass == null && javaArgs == null) { 22 | return ir; 23 | } else { 24 | return new IntegrationResult( 25 | nativeImagePath != null ? nativeImagePath : ir.nativeImagePath, 26 | mainClass != null ? mainClass : ir.mainClass, 27 | javaArgs != null ? javaArgs : ir.javaArgs); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/ConsoleInputReadTask.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.concurrent.Callable; 8 | 9 | public class ConsoleInputReadTask implements Callable { 10 | private final InputStream in; 11 | 12 | public ConsoleInputReadTask(InputStream in) { 13 | this.in = in; 14 | } 15 | 16 | public String call() throws IOException { 17 | BufferedReader br = new BufferedReader(new InputStreamReader(in)); 18 | String input; 19 | do { 20 | try { 21 | // wait until we have data to complete a readLine() 22 | while (!br.ready()) { 23 | Thread.sleep(200); 24 | } 25 | input = br.readLine(); 26 | } catch (InterruptedException e) { 27 | return null; 28 | } 29 | } while ("".equals(input)); 30 | return input; 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/ConsoleOutput.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import picocli.CommandLine; 4 | 5 | public class ConsoleOutput { 6 | public static String yellow(String text) { 7 | return CommandLine.Help.Ansi.AUTO.new Text("@|fg(yellow) " + text + "|@").toString(); 8 | } 9 | 10 | public static String cyan(String text) { 11 | return CommandLine.Help.Ansi.AUTO.new Text("@|fg(cyan) " + text + "|@").toString(); 12 | } 13 | 14 | public static String magenta(String text) { 15 | return CommandLine.Help.Ansi.AUTO.new Text("@|fg(magenta) " + text + "|@").toString(); 16 | } 17 | 18 | public static String faint(String text) { 19 | return CommandLine.Help.Ansi.AUTO.new Text("@|faint " + text + "|@").toString(); 20 | } 21 | 22 | public static String bold(String text) { 23 | return CommandLine.Help.Ansi.AUTO.new Text("@|bold " + text + "|@").toString(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/FileTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import com.google.gson.TypeAdapter; 7 | import com.google.gson.stream.JsonReader; 8 | import com.google.gson.stream.JsonToken; 9 | import com.google.gson.stream.JsonWriter; 10 | 11 | public class FileTypeAdapter extends TypeAdapter { 12 | @Override 13 | public File read(JsonReader in) throws IOException { 14 | if (in.peek() == JsonToken.NULL) { 15 | in.nextNull(); 16 | return null; 17 | } 18 | String path = in.nextString(); 19 | return new File(path); 20 | } 21 | 22 | @Override 23 | public void write(JsonWriter out, File path) throws IOException { 24 | if (path == null) { 25 | out.nullValue(); 26 | return; 27 | } 28 | out.value(path.getPath()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/JBangFormatter.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import java.util.Date; 6 | import java.util.logging.Formatter; 7 | import java.util.logging.Level; 8 | import java.util.logging.LogRecord; 9 | 10 | /** 11 | * This JUL Formatter is used to format JUL log messages in such a way that they 12 | * look similar to JBang log messages. 13 | */ 14 | public class JBangFormatter extends Formatter { 15 | private final Date dat = new Date(); 16 | 17 | @Override 18 | public synchronized String format(LogRecord record) { 19 | dat.setTime(record.getMillis()); 20 | String source; 21 | if (record.getSourceClassName() != null) { 22 | source = record.getSourceClassName(); 23 | if (record.getSourceMethodName() != null) { 24 | source += " " + record.getSourceMethodName(); 25 | } 26 | } else { 27 | source = record.getLoggerName(); 28 | } 29 | String message = formatMessage(record); 30 | String throwable = ""; 31 | if (record.getThrown() != null) { 32 | StringWriter sw = new StringWriter(); 33 | PrintWriter pw = new PrintWriter(sw); 34 | pw.println(); 35 | record.getThrown().printStackTrace(pw); 36 | pw.close(); 37 | throwable = sw.toString(); 38 | } 39 | String format = "[jbang] "; 40 | if (Util.isVerbose()) { 41 | format += "[%1$tF %1$tT] "; 42 | } 43 | if (record.getLevel().intValue() > Level.INFO.intValue()) { 44 | format += "[%4$s] "; 45 | } 46 | format += "%5$s%n"; 47 | return String.format(format, 48 | dat, 49 | source, 50 | record.getLoggerName(), 51 | record.getLevel().getLocalizedName(), 52 | message, 53 | throwable); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/PathTypeAdapter.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | 7 | import com.google.gson.TypeAdapter; 8 | import com.google.gson.stream.JsonReader; 9 | import com.google.gson.stream.JsonToken; 10 | import com.google.gson.stream.JsonWriter; 11 | 12 | public class PathTypeAdapter extends TypeAdapter { 13 | @Override 14 | public Path read(JsonReader in) throws IOException { 15 | if (in.peek() == JsonToken.NULL) { 16 | in.nextNull(); 17 | return null; 18 | } 19 | String path = in.nextString(); 20 | return Paths.get(path); 21 | } 22 | 23 | @Override 24 | public void write(JsonWriter out, Path path) throws IOException { 25 | if (path == null) { 26 | out.nullValue(); 27 | return; 28 | } 29 | out.value(path.toString()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/dev/jbang/util/TemplateEngine.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.io.Reader; 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.Optional; 8 | 9 | import dev.jbang.source.ResourceRef; 10 | 11 | import io.quarkus.qute.Engine; 12 | import io.quarkus.qute.ReflectionValueResolver; 13 | import io.quarkus.qute.Template; 14 | import io.quarkus.qute.TemplateLocator; 15 | import io.quarkus.qute.Variant; 16 | 17 | public class TemplateEngine { 18 | final Engine engine; 19 | 20 | static TemplateEngine instance; 21 | 22 | TemplateEngine() { 23 | engine = Engine.builder() 24 | .addDefaults() 25 | .removeStandaloneLines(true) 26 | .addValueResolver(new ReflectionValueResolver()) 27 | // .addResultMapper(new PropertyNotFoundThrowException()) 28 | .addLocator(this::locate) 29 | .build(); 30 | } 31 | 32 | /** 33 | * @param ref 34 | * @return the optional reader 35 | */ 36 | private Optional locate(String ref) { 37 | return Optional.of(new ResourceRefTemplateLocation(ResourceRef.forResource(ref))); 38 | } 39 | 40 | public Template getTemplate(ResourceRef templateRef) { 41 | return engine.getTemplate(templateRef.getOriginalResource()); 42 | } 43 | 44 | static class ResourceRefTemplateLocation implements TemplateLocator.TemplateLocation { 45 | private final ResourceRef resourceRef; 46 | private Optional variant = Optional.empty(); 47 | 48 | public ResourceRefTemplateLocation(ResourceRef resourceRef) { 49 | this.resourceRef = resourceRef; 50 | this.variant = Optional.empty(); 51 | } 52 | 53 | @Override 54 | public Reader read() { 55 | try { 56 | return new InputStreamReader(resourceRef.getInputStream(), StandardCharsets.UTF_8); 57 | } catch (IOException e) { 58 | return null; 59 | } 60 | } 61 | 62 | @Override 63 | public Optional getVariant() { 64 | return variant; 65 | } 66 | 67 | } 68 | 69 | public static TemplateEngine instance() { 70 | if (instance == null) { 71 | instance = new TemplateEngine(); 72 | } 73 | return instance; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java9/dev/jbang/util/ModuleUtil9.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.lang.module.FindException; 4 | import java.lang.module.ModuleFinder; 5 | import java.lang.module.ModuleReference; 6 | import java.nio.file.Path; 7 | import java.util.List; 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * WARNING: This file MUST be compiled with Java 9+ 13 | */ 14 | public class ModuleUtil9 { 15 | public static String getModuleName(Path file) { 16 | try { 17 | Set refs = ModuleFinder.of(file).findAll(); 18 | if (!refs.isEmpty()) { 19 | return refs.iterator().next().descriptor().name(); 20 | } 21 | } catch (FindException ex) { 22 | // Ignore 23 | } 24 | return null; 25 | } 26 | 27 | public static List listJdkModules() { 28 | ModuleLayer ml = ModuleLayer.boot(); 29 | return ml.modules() 30 | .stream() 31 | .filter(m -> m.isNamed() && m.getAnnotation(Deprecated.class) == null 32 | && (m.getName().startsWith("java.") || m.getName().startsWith("jdk.")) 33 | && (!m.getName().equals("jdk.naming.ldap"))) 34 | .map(m -> m.getName()) 35 | .collect(Collectors.toList()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/.qute.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {#for item in classpath} 10 | 11 | {/for} 12 | 13 | -------------------------------------------------------------------------------- /src/main/resources/.qute.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | {baseName} 4 | Temporary project generated by jbang 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/README.qute.md: -------------------------------------------------------------------------------- 1 | ## jbang project for {baseName} 2 | 3 | This is a "virtual" project directory for the jbang script {baseName}. 4 | 5 | This lets you get content assist, debugging, etc. for Java in most modern editors and IDE's. 6 | 7 | JBang tested this to work in the following IDE's: 8 | 9 | * Eclipse 10 | * IntelliJ 11 | * Visual Studio Code 12 | * Netbeans 13 | * vi 14 | * emacs 15 | 16 | ## Enjoy 17 | 18 | Have fun and if you like this consider following [@jbangdev](http://twitter.com/jbangdev) and give a 19 | star to [jbangdev/jbang](https://github.com/jbangdev/jbang). 20 | 21 | If you have issues or suggestions please [open an issue](https://github.com/jbangdev/jbang/issues/new). 22 | 23 | With love,
24 | [jbang.dev](https://jbang.dev) 25 | -------------------------------------------------------------------------------- /src/main/resources/build.qute.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'application' 4 | } 5 | 6 | repositories { 7 | mavenLocal() 8 | {#for url in repositories} 9 | maven { 10 | url "{url}" 11 | } 12 | {/for} 13 | } 14 | 15 | dependencies { 16 | {#for item in gradledependencies} 17 | {item} 18 | {/for} 19 | } 20 | 21 | application { 22 | mainClass = '{fullClassName}' 23 | } 24 | 25 | sourceSets.main.java.srcDirs 'src' 26 | sourceSets.test.java.srcDirs 'src' 27 | -------------------------------------------------------------------------------- /src/main/resources/dist/gradle/gradle/wrapper/gradle-wrapper-jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/src/main/resources/dist/gradle/gradle/wrapper/gradle-wrapper-jar -------------------------------------------------------------------------------- /src/main/resources/dist/gradle/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/resources/dist/gradle/update-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export GRADLE_VERSION=8.9 4 | 5 | mv gradle/wrapper/gradle-wrapper-jar gradle/wrapper/gradle-wrapper.jar 6 | 7 | touch build.gradle 8 | touch settings.gradle 9 | 10 | ./gradlew --no-daemon wrapper --gradle-version $GRADLE_VERSION 11 | 12 | mv gradle/wrapper/gradle-wrapper.jar gradle/wrapper/gradle-wrapper-jar 13 | 14 | rm -f -r .gradle build.gradle settings.gradle 15 | 16 | tree -a 17 | 18 | git status 19 | git diff 20 | -------------------------------------------------------------------------------- /src/main/resources/dist/maven/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. 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 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /src/main/resources/dist/maven/update-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export MAVEN_VERSION=3.9.9 4 | 5 | pomXML=' 6 | 8 | 4.0.0 9 | groupId 10 | artifactid 11 | 1.0-SNAPSHOT 12 | jar 13 | projectName 14 | 15 | 16 | UTF-8 17 | 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 2.5.1 25 | 26 | 1.6 27 | 1.6 28 | 29 | 30 | 31 | 32 | 33 | ' 34 | 35 | echo "$pomXML" > pom.xml 36 | 37 | mvn -N wrapper:wrapper -Dmaven=$MAVEN_VERSION 38 | 39 | rm -f -r pom.xml 40 | 41 | tree -a 42 | 43 | git status 44 | git diff 45 | -------------------------------------------------------------------------------- /src/main/resources/export-build.qute.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | {#if language eq 'groovy'} 3 | id 'groovy' 4 | {/if} 5 | {#if language eq 'java'} 6 | id 'java' 7 | {/if} 8 | {#if language eq 'kotlin'} 9 | id 'org.jetbrains.kotlin.jvm' version '{kotlinVersion}' 10 | {/if} 11 | id 'application' 12 | } 13 | 14 | {#if description} 15 | description = '{description}' 16 | {/if} 17 | 18 | repositories { 19 | mavenCentral() 20 | {#for url in repositories} 21 | maven { 22 | url "{url}" 23 | } 24 | {/for} 25 | mavenLocal() 26 | } 27 | 28 | {#if javaVersion} 29 | java { 30 | toolchain { 31 | languageVersion = JavaLanguageVersion.of({javaVersion}) 32 | } 33 | } 34 | {/if} 35 | 36 | {#if !gradledependencies.empty} 37 | dependencies { 38 | {#for item in gradledependencies} 39 | {item} 40 | {/for} 41 | } 42 | {/if} 43 | 44 | application { 45 | mainClass = '{fullClassName}' 46 | applicationDefaultJvmArgs = [{jvmArgs}] 47 | {#if enablePreview eq 'true'} 48 | applicationDefaultJvmArgs += ['--enable-preview'] 49 | {/if} 50 | } 51 | 52 | {#if language eq 'java'} 53 | compileJava { 54 | {#if enablePreview eq 'true'} 55 | options.compilerArgs += ['--release', '{javaVersion}', '--enable-preview', '-Xlint:preview'] 56 | {/if} 57 | {#if compilerArgs ne ""} 58 | options.compilerArgs += [{compilerArgs}] 59 | {/if} 60 | } 61 | {/if} 62 | 63 | {#if language eq 'groovy'} 64 | compileGroovy { 65 | {#if compilerArgs ne ""} 66 | options.compilerArgs += [{compilerArgs}] 67 | {/if} 68 | } 69 | {/if} 70 | 71 | {#if language eq 'kotlin'} 72 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask 73 | tasks.named('compileKotlin', KotlinCompilationTask) { 74 | compilerOptions { 75 | {#if compilerArgs ne ""} 76 | freeCompilerArgs.addAll([{compilerArgs}]) 77 | {/if} 78 | } 79 | } 80 | {/if} 81 | 82 | jar { 83 | manifest { 84 | attributes( 85 | 'Main-Class': '{fullClassName}', 86 | ) 87 | } 88 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 89 | } 90 | -------------------------------------------------------------------------------- /src/main/resources/idea-port-4004.qute.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /src/main/resources/idea.qute.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /src/main/resources/init-agent.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | {#for dep in dependencies.orEmpty} 3 | //DEPS {dep} 4 | {/for} 5 | {#if dependencies.isEmpty()}// //DEPS {/if} 6 | //JAVAAGENT Can-Redefine-Classes Can-Retransform-Classes Can-Set-Native-Method-Prefix 7 | 8 | import java.lang.instrument.ClassFileTransformer; 9 | import java.lang.instrument.IllegalClassFormatException; 10 | import java.lang.instrument.Instrumentation; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | import java.security.ProtectionDomain; 15 | 16 | 17 | public class {baseName} { 18 | 19 | public static void premain(String agentArgs, Instrumentation instrumentation) { 20 | System.out.println("jbang agent {baseName} loaded. Will dump all loaded classes into `classes/`"); 21 | 22 | ClassLogger transformer = new ClassLogger(); 23 | instrumentation.addTransformer(transformer); 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println("This is a (jbang) javaagent.\n" + 28 | "Usage: \n" + 29 | " jbang --javaagent={baseName}.java yourApp.java"); 30 | } 31 | 32 | static public class ClassLogger implements ClassFileTransformer { 33 | @Override 34 | public byte[] transform(ClassLoader loader, 35 | String className, 36 | Class classBeingRedefined, 37 | ProtectionDomain protectionDomain, 38 | byte[] classfileBuffer) throws IllegalClassFormatException { 39 | try { 40 | Path path = Paths.get("classes/" + className + ".class"); 41 | Files.createDirectories(path.getParent()); 42 | Files.write(path, classfileBuffer); 43 | } catch (Throwable ignored) { 44 | System.err.println(ignored); 45 | } finally { return classfileBuffer; } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/init-cli.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //DEPS info.picocli:picocli:4.6.3 3 | {#for dep in dependencies.orEmpty} 4 | //DEPS {dep} 5 | {/for} 6 | {#if dependencies.isEmpty()}// //DEPS {/if} 7 | 8 | import picocli.CommandLine; 9 | import picocli.CommandLine.Command; 10 | import picocli.CommandLine.Parameters; 11 | 12 | import java.util.concurrent.Callable; 13 | 14 | @Command(name = "{baseName}", mixinStandardHelpOptions = true, version = "{baseName} 0.1", 15 | description = "{baseName} made with jbang") 16 | class {baseName} implements Callable { 17 | 18 | @Parameters(index = "0", description = "The greeting to print", defaultValue = "World!") 19 | private String greeting; 20 | 21 | public static void main(String... args) { 22 | int exitCode = new CommandLine(new {baseName}()).execute(args); 23 | System.exit(exitCode); 24 | } 25 | 26 | @Override 27 | public Integer call() throws Exception { // your business logic goes here... 28 | System.out.println("Hello " + greeting); 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/init-hello.groovy.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | {#for dep in dependencies.orEmpty} 3 | //DEPS {dep} 4 | {/for} 5 | {#if dependencies.isEmpty()}// //DEPS {/if} 6 | 7 | {#if magiccontent} 8 | {magiccontent} 9 | {#else} 10 | println("Hello World"); 11 | {/if} 12 | -------------------------------------------------------------------------------- /src/main/resources/init-hello.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | {#for dep in dependencies.orEmpty} 3 | //DEPS {dep} 4 | {/for} 5 | {#if dependencies.isEmpty()}// //DEPS {/if} 6 | 7 | {#if magiccontent} 8 | {magiccontent} 9 | {#else} 10 | import static java.lang.System.*; 11 | 12 | public class {baseName} { 13 | 14 | public static void main(String... args) { 15 | out.println("Hello World"); 16 | } 17 | } 18 | {/if} -------------------------------------------------------------------------------- /src/main/resources/init-hello.kt.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | 3 | {#for dep in dependencies.orEmpty} 4 | //DEPS {dep} 5 | {/for} 6 | {#if dependencies.isEmpty()}// //DEPS {/if} 7 | 8 | {#if magiccontent} 9 | {magiccontent} 10 | {#else} 11 | public fun main() { 12 | println("Hello World") 13 | } 14 | {/if} -------------------------------------------------------------------------------- /src/main/resources/init-qcli.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //JAVA 17+ 3 | // Update the Quarkus version to what you want here or run jbang with 4 | // `-Dquarkus.version=` to override it. 5 | //DEPS io.quarkus:quarkus-bom:$\{quarkus.version:3.15.1\}@pom 6 | //DEPS io.quarkus:quarkus-picocli 7 | {#for dep in dependencies.orEmpty} 8 | //DEPS {dep} 9 | {/for} 10 | //Q:CONFIG quarkus.banner.enabled=false 11 | //Q:CONFIG quarkus.log.level=WARN 12 | 13 | import picocli.CommandLine; 14 | 15 | import jakarta.enterprise.context.Dependent; 16 | import jakarta.inject.Inject; 17 | import io.quarkus.runtime.annotations.QuarkusMain; 18 | import io.quarkus.runtime.QuarkusApplication; 19 | import io.quarkus.runtime.Quarkus; 20 | 21 | @CommandLine.Command 22 | public class {baseName} implements Runnable { 23 | 24 | @CommandLine.Parameters(index = "0", description = "The greeting to print", defaultValue = "World!") 25 | String name; 26 | 27 | @Inject 28 | CommandLine.IFactory factory; 29 | 30 | private final GreetingService greetingService; 31 | 32 | public {baseName}(GreetingService greetingService) { 33 | this.greetingService = greetingService; 34 | } 35 | 36 | @Override 37 | public void run() { 38 | greetingService.sayHello(name); 39 | } 40 | 41 | } 42 | 43 | @Dependent 44 | class GreetingService { 45 | void sayHello(String name) { 46 | System.out.println("Hello " + name + "!"); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/resources/init-qrest.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | //JAVA 17+ 3 | // Update the Quarkus version to what you want here or run jbang with 4 | // `-Dquarkus.version=` to override it. 5 | //DEPS io.quarkus:quarkus-bom:$\{quarkus.version:3.15.1\}@pom 6 | //DEPS io.quarkus:quarkus-rest 7 | // //DEPS io.quarkus:quarkus-smallrye-openapi 8 | // //DEPS io.quarkus:quarkus-swagger-ui 9 | //JAVAC_OPTIONS -parameters 10 | 11 | import io.quarkus.runtime.Quarkus; 12 | import jakarta.enterprise.context.ApplicationScoped; 13 | import jakarta.ws.rs.GET; 14 | import jakarta.ws.rs.Path; 15 | 16 | @Path("/hello") 17 | @ApplicationScoped 18 | public class {baseName} { 19 | 20 | @GET 21 | public String sayHello() { 22 | return "Hello from Quarkus with jbang.dev"; 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/main/resources/init-readme.md.qute: -------------------------------------------------------------------------------- 1 | ## Read Me Example 2 | 3 | Welcome to a basic example on how to do a readme.md file that can be run with JBang: 4 | 5 | ```java 6 | {#for dep in dependencies.orEmpty} 7 | //DEPS {dep} 8 | {/for} 9 | {#if dependencies.isEmpty()}// //DEPS {/if} 10 | System.out.println("Hello World"); 11 | ``` 12 | 13 | You can run this using `jbang {scriptref}` 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/initClass.java.qute: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | {#for dep in dependencies.orEmpty} 3 | //DEPS {dep} 4 | {/for} 5 | {#if dependencies.isEmpty()}// //DEPS {/if} 6 | 7 | import static java.lang.System.*; 8 | 9 | public class {baseName} { 10 | 11 | public static void main(String... args) { 12 | out.println("Hello World"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/jbang.properties: -------------------------------------------------------------------------------- 1 | format=text 2 | init.template=hello 3 | jdkproviders=current,default,javahome,path,jbang 4 | run.debug=4004 5 | run.jfr=filename={baseName}.jfr 6 | wrapper.install.dir=. 7 | -------------------------------------------------------------------------------- /src/main/resources/jbang_icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbangdev/jbang/2aad090f36156a993b7d86553381e571603c86ca/src/main/resources/jbang_icon_64x64.png -------------------------------------------------------------------------------- /src/main/resources/launch.qute.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "{baseName}-port-4004", 10 | "request": "attach", 11 | "hostName": "localhost", 12 | "port": 4004 13 | }, 14 | { 15 | "type": "java", 16 | "name": "Debug (Launch) - {baseName}", 17 | "request": "launch", 18 | "mainClass": "{baseName}", 19 | "projectName": "{baseName}" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers=java.util.logging.ConsoleHandler 2 | .level=INFO 3 | java.util.logging.ConsoleHandler.level=ALL 4 | java.util.logging.ConsoleHandler.formatter=dev.jbang.util.JBangFormatter 5 | -------------------------------------------------------------------------------- /src/main/resources/main-port-4004.qute.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/main.qute.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/module-info.qute.java: -------------------------------------------------------------------------------- 1 | module {moduleName} { 2 | {#for item in dependencies} 3 | requires {item}; 4 | {/for} 5 | opens {packageName}; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/pom.qute.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | {group} 7 | {artifact} 8 | {version} 9 | {description} 10 | 11 | {#for item in dependencies} 12 | 13 | {item.coordinate.groupId} 14 | {item.coordinate.artifactId} 15 | {item.coordinate.version} 16 | compile 17 | 18 | {/for} 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/settings.qute.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.import.gradle.enabled": false, 3 | "java.import.maven.enabled": false, 4 | "java.eclipse.downloadSources": true, 5 | "files.exclude": { 6 | "bin/":true, 7 | ".eclipse/":true, 8 | ".project":true, 9 | ".classpath":true, 10 | "build.gradle":true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/trusted-sources.json.qute: -------------------------------------------------------------------------------- 1 | // URL's matching one or more entries in the list below will be trusted to be runnable by jbang. 2 | // The following examples show what entries can look like: 3 | // - "https://jbang.dev": Matches this specific domain using https 4 | // - "https://jbang.dev/foo": Matches https://jbang.dev/foo and https://jbang.dev/foo/bar, 5 | // but not https://jbang.dev/foobar or https://jbang.dev/bar 6 | // - "https://*.jbang.dev": Match all domains ending in "jbang.dev" using https 7 | // - "jbang.dev": Match this specific domain using either http or https 8 | // - "*.jbang.dev": Match all domains ending in "jbang.dev" using either http or https 9 | // - "*": Match all sources using either http or https (This effectively disables any checks. Be careful!) 10 | // 11 | // By default, jbang trusts "localhost" and file://. 12 | // You can use the "jbang --trust=rule1,rule2,.." command to add to this file. 13 | // Note: --trust will rewrite this file. Preserving just the elements. Additional data and comments will not be kept. 14 | [ 15 | {#for item in trustedsources}{item}{#if hasNext},{/if} 16 | {/for} 17 | ] -------------------------------------------------------------------------------- /src/main/scripts/choco/tools/LICENSE.txt: -------------------------------------------------------------------------------- 1 | From: https://raw.githubusercontent.com/jbangdev/jbang/HEAD/LICENSE 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020 Max Rydahl Andersen 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /src/main/scripts/choco/tools/VERIFICATION.txt: -------------------------------------------------------------------------------- 1 |  2 | VERIFICATION 3 | Verification is intended to assist the Chocolatey moderators and community 4 | in verifying that this package's contents are trustworthy. 5 | 6 | You can verify the files are same as the one coming from the main repo 7 | at https://github.com/jbangdev/jbang/releases. 8 | -------------------------------------------------------------------------------- /src/main/scripts/choco/tools/chocolateyinstall.ps1: -------------------------------------------------------------------------------- 1 | $tools = Split-Path $MyInvocation.MyCommand.Definition 2 | $package = Split-Path $tools 3 | $jbang_home = Join-Path $package 'jbang-@projectVersion@' 4 | $jbang_bat = Join-Path $jbang_home 'bin/jbang.cmd' 5 | 6 | Install-ChocolateyZipPackage ` 7 | -PackageName 'jbang' ` 8 | -Url 'https://github.com/jbangdev/jbang/releases/download/v@projectVersion@/jbang-@projectVersion@.zip' ` 9 | -Checksum '@sha256@' ` 10 | -ChecksumType 'sha256' ` 11 | -UnzipLocation $package 12 | 13 | Install-BinFile -Name 'jbang' -Path $jbang_bat -------------------------------------------------------------------------------- /src/main/scripts/choco/tools/chocolateyuninstall.ps1: -------------------------------------------------------------------------------- 1 | $tools = Split-Path $MyInvocation.MyCommand.Definition 2 | $package = Split-Path $tools 3 | $jbang_home = Join-Path $package 'jbang-@projectVersion@' 4 | $jbang_bat = Join-Path $jbang_home 'bin/jbang.cmd' 5 | 6 | Uninstall-BinFile -Name 'jbang' -Path $jbang_bat 7 | -------------------------------------------------------------------------------- /src/main/scripts/spec/jbang.spec: -------------------------------------------------------------------------------- 1 | Name: jbang 2 | Version: @projectVersion@ 3 | Release: 1%{?dist} 4 | Summary: Unleash the power of Java 5 | 6 | License: MIT 7 | URL: https://github.com/jbangdev/%{name} 8 | Source0: https://github.com/jbangdev/%{name}/releases/download/v%{version}/%{name}-%{version}.tar 9 | 10 | BuildArch: noarch 11 | BuildRequires: git 12 | Requires: java 13 | 14 | %description 15 | Unleash the power of Java 16 | 17 | Want to learn or explore Java instantly without setup ? 18 | 19 | Do you like Java but uses python, groovy, kotlin or 20 | similar languages for your scripts ? 21 | 22 | Ever tried out Java 10+ support for running .java files 23 | directly in your shell but felt it was a bit too cumbersome ? 24 | 25 | Then try jbang which lets you do this: 26 | 27 | $ jbang --init=cli hello.java 28 | $ jbang hello.java Max! 29 | [jbang] Resolving dependencies... 30 | [jbang] Resolving info.picocli:picocli:4.6.3...Done 31 | [jbang] Dependencies resolved 32 | [jbang] Building jar... 33 | Hello Max! 34 | $ jbang hello.java -h 35 | Usage: hello [-hV] 36 | hello made with jbang 37 | The greeting to print 38 | -h, --help Show this help message and exit. 39 | -V, --version Print version information and exit. 40 | 41 | Instant cli app generated built using java and picocli as a dependency that was fetched as needed for the compilation and execution. 42 | 43 | %prep 44 | %autosetup -S git 45 | 46 | 47 | %install 48 | #mkdir -p %{buildroot}%{_javadir} 49 | mkdir -p %{buildroot}%{_bindir} 50 | install -p -m 644 bin/%{name}.jar %{buildroot}%{_bindir}/%{name}.jar 51 | install -p -m 755 bin/%{name} %{buildroot}%{_bindir}/%{name} 52 | 53 | %files 54 | %{_bindir}/jbang.jar 55 | %{_bindir}/jbang -------------------------------------------------------------------------------- /src/main/scripts/test.cmd: -------------------------------------------------------------------------------- 1 | @@ECHO off 2 | @@setlocal EnableDelayedExpansion 3 | @@set LF=^ 4 | 5 | 6 | @@SET command=# 7 | @@FOR /F "tokens=*" %%i in ('findstr -bv @@ "%~f0"') DO SET command=!command!!LF!%%i 8 | @@powershell -noprofile -noexit -command !command! & goto:eof 9 | 10 | 11 | # *** POWERSHELL CODE STARTS HERE *** # 12 | Write-Host 'This is PowerShell code being run from inside a batch file!' -Fore red 13 | $PSVersionTable 14 | Get-Process -Id $PID | Format-Table 15 | Exit 16 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/JBangHandler.java: -------------------------------------------------------------------------------- 1 | package dev.jbang; 2 | 3 | import java.io.OutputStream; 4 | import java.util.logging.LogRecord; 5 | import java.util.logging.StreamHandler; 6 | 7 | import dev.jbang.util.JBangFormatter; 8 | 9 | public class JBangHandler extends StreamHandler { 10 | private OutputStream currentOut; 11 | 12 | public JBangHandler() { 13 | super(System.err, new JBangFormatter()); 14 | currentOut = System.err; 15 | } 16 | 17 | @Override 18 | public void publish(LogRecord record) { 19 | updateStream(); 20 | super.publish(record); 21 | flush(); 22 | } 23 | 24 | @Override 25 | public void close() { 26 | updateStream(); 27 | flush(); 28 | } 29 | 30 | private void updateStream() { 31 | if (currentOut != System.err) { 32 | setOutputStream(System.err); 33 | currentOut = System.err; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/TestImplicitAlias.java: -------------------------------------------------------------------------------- 1 | package dev.jbang; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | 8 | import org.hamcrest.Matchers; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import dev.jbang.catalog.Alias; 12 | import dev.jbang.catalog.ImplicitCatalogRef; 13 | 14 | /** 15 | * TODO: use mock to handle https lookups instead of jbang.dev 16 | */ 17 | public class TestImplicitAlias extends BaseTest { 18 | 19 | @Test 20 | public void testGitImplicitCatalog() { 21 | assertThat(ImplicitCatalogRef.resolveImplicitCatalogUrl("jbangdev").get(), 22 | Matchers.equalTo("https://github.com/jbangdev/jbang-catalog/blob/HEAD/jbang-catalog.json")); 23 | assertThat(ImplicitCatalogRef.resolveImplicitCatalogUrl("jbangdev/jbang-examples").get(), 24 | Matchers.equalTo("https://github.com/jbangdev/jbang-examples/blob/HEAD/jbang-catalog.json")); 25 | } 26 | 27 | @Test 28 | public void testImplictURLAlias() { 29 | 30 | Alias url = Alias.get("tree@xam.dk"); 31 | assertThat(url.scriptRef, Matchers.equalTo("tree/main.java")); 32 | 33 | } 34 | 35 | @Test 36 | public void testImplictExplicitURLAlias() { 37 | 38 | Alias url = Alias.get("tree@https://xam.dk"); 39 | assertThat(url.scriptRef, Matchers.equalTo("tree/main.java")); 40 | 41 | } 42 | 43 | // @Test needs fixing to not generate absolute paths but instead relative paths. 44 | public void testFileURLAlias() throws Exception { 45 | 46 | assertThat(jbangTempDir.resolve("inner").toFile().mkdirs(), Matchers.is(true)); 47 | 48 | Files.copy(examplesTestFolder.resolve("helloworld.java"), jbangTempDir.resolve("inner/helloworld.java")); 49 | String src = jbangTempDir.resolve("inner/helloworld.java").toString(); 50 | Path path = jbangTempDir.resolve("jbang-catalog.json"); 51 | 52 | checkedRun(null, "alias", "add", "-f", path.toString(), "--name=apptest", src); 53 | 54 | String url = "apptest@" + path.toUri(); 55 | assertThat(url, Matchers.stringContainsInOrder("file://")); 56 | 57 | Alias alias = Alias.get(url); 58 | 59 | assertThat(alias.scriptRef, Matchers.equalTo("helloworld.java")); 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/cli/TestSettings.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.cli; 2 | 3 | import static org.hamcrest.Matchers.endsWith; 4 | import static org.hamcrest.Matchers.nullValue; 5 | import static org.junit.Assert.assertThat; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import dev.jbang.BaseTest; 10 | import dev.jbang.Settings; 11 | 12 | public class TestSettings extends BaseTest { 13 | 14 | @Test 15 | void testRepo() { 16 | environmentVariables.clear("JBANG_REPO"); 17 | assertThat(Settings.getJBangLocalMavenRepoOverride(), nullValue()); 18 | environmentVariables.set("JBANG_REPO", "envrepo"); 19 | assertThat(Settings.getJBangLocalMavenRepoOverride().toString(), endsWith("envrepo")); 20 | environmentVariables.clear("JBANG_REPO"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/dependencies/TestArtifactInfo.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.dependencies; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.Matchers.*; 5 | import static org.hamcrest.io.FileMatchers.aFileWithSize; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | import org.hamcrest.MatcherAssert; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import dev.jbang.BaseTest; 15 | import dev.jbang.Settings; 16 | 17 | public class TestArtifactInfo extends BaseTest { 18 | 19 | @Test 20 | public void testDependencyCache() { 21 | DependencyCache.clear(); 22 | 23 | List deps = Arrays.asList( 24 | "org.apache.commons:commons-configuration2:2.7", 25 | "org.apache.commons:commons-text:1.8"); 26 | 27 | ModularClassPath classpath = DependencyUtil.resolveDependencies(deps, Collections.emptyList(), false, false, 28 | false, 29 | true, false); 30 | 31 | DependencyCache.cache("wonka", classpath.getArtifacts()); 32 | 33 | MatcherAssert.assertThat(Settings.getCacheDependencyFile().toFile(), aFileWithSize(greaterThan(10L))); 34 | 35 | List wonka = DependencyCache.findDependenciesByHash("wonka"); 36 | 37 | assertThat(wonka, notNullValue()); 38 | assertThat(wonka, hasSize(4)); 39 | 40 | assertThat(wonka, contains(classpath.getArtifacts().toArray())); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/dependencies/TestGrape.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.dependencies; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.Matchers.hasItem; 5 | import static org.hamcrest.Matchers.not; 6 | 7 | import java.io.FileNotFoundException; 8 | import java.util.List; 9 | 10 | import org.junit.jupiter.api.Test; 11 | 12 | import dev.jbang.BaseTest; 13 | import dev.jbang.source.Project; 14 | import dev.jbang.source.Source; 15 | import dev.jbang.source.sources.JavaSource; 16 | 17 | public class TestGrape extends BaseTest { 18 | 19 | @Test 20 | void testFindGrabs() throws FileNotFoundException { 21 | 22 | String grabBlock = "@Grapes({\n" + 23 | "\t\t@Grab(\"log4j:log4j:1.2.17\"),\n" + 24 | "\t\t@Grab(group = \"org.hibernate\", module = \"hibernate-core\", version = \"5.4.10.Final\"),\n" + 25 | "\t\t@Grab(group=\"net.sf.json-lib\", module=\"json-lib\", version=\"2.2.3\", classifier=\"jdk15\"), // classifier\n" 26 | + 27 | "\t\t@Grab(group=\"org.restlet\", version=\"1.1.6\", module=\"org.restlet\") // different order\n" + 28 | "\t\t@Grab(group=\"org.restlet\", version=\"1.1.6\", module=\"org.restlet\", ext=\"wonka\") // different order\n" 29 | + 30 | "\t//\t@Grab(group=\"blah\", version=\"1.0\", module=\"borked\", ext=\"wonka\") // commented\n" 31 | + 32 | "})\n"; 33 | 34 | Source src = new JavaSource(grabBlock, null); 35 | Project prj = Project.builder().build(src); 36 | List deps = prj.getMainSourceSet().getDependencies(); 37 | 38 | assertThat(deps, hasItem("org.hibernate:hibernate-core:5.4.10.Final")); 39 | assertThat(deps, hasItem("net.sf.json-lib:json-lib:2.2.3:jdk15")); 40 | assertThat(deps, hasItem("org.restlet:org.restlet:1.1.6")); 41 | assertThat(deps, hasItem("log4j:log4j:1.2.17")); 42 | assertThat(deps, not(hasItem("blah:borked:1.0@wonka"))); 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/net/TestTrustEdit.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.net; 2 | 3 | import static org.hamcrest.Matchers.arrayContaining; 4 | import static org.hamcrest.Matchers.arrayWithSize; 5 | import static org.hamcrest.Matchers.not; 6 | import static org.hamcrest.io.FileMatchers.anExistingFile; 7 | import static org.junit.Assert.assertThat; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.Arrays; 12 | import java.util.Collections; 13 | 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.jupiter.api.io.TempDir; 16 | 17 | import dev.jbang.BaseTest; 18 | 19 | public class TestTrustEdit extends BaseTest { 20 | 21 | @Test 22 | void testAddTrust(@TempDir File storage) throws IOException { 23 | 24 | File settings = new File(storage, "sources.json"); 25 | 26 | TrustedSources td = new TrustedSources(new String[0]); 27 | 28 | assertThat(settings, not(anExistingFile())); 29 | 30 | td.add(Collections.singletonList("a"), settings); 31 | 32 | assertThat(settings, anExistingFile()); 33 | 34 | TrustedSources sources = TrustedSources.load(settings.toPath()); 35 | 36 | assertThat(sources.getTrustedSources(), arrayWithSize(1)); 37 | assertThat(sources.getTrustedSources(), arrayContaining("a")); 38 | 39 | } 40 | 41 | @Test 42 | void testMultiAddTrust(@TempDir File storage) throws IOException { 43 | 44 | File settings = new File(storage, "sources.json"); 45 | 46 | TrustedSources td = new TrustedSources(new String[0]); 47 | 48 | assertThat(settings, not(anExistingFile())); 49 | 50 | td.add(Arrays.asList("a", "b"), settings); 51 | 52 | assertThat(settings, anExistingFile()); 53 | 54 | TrustedSources trustedSources = TrustedSources.load(settings.toPath()); 55 | 56 | assertThat(trustedSources.getTrustedSources(), arrayContaining("a", "b")); 57 | 58 | trustedSources.add(Collections.singletonList("c"), settings); 59 | 60 | assertThat(trustedSources.getTrustedSources(), arrayContaining("a", "b", "c")); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/source/TestProject.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertFalse; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | import dev.jbang.BaseTest; 9 | import dev.jbang.source.sources.JavaSource; 10 | 11 | public class TestProject extends BaseTest { 12 | 13 | @Test 14 | void testCDS() { 15 | Source source = new JavaSource("//CDS\nclass m { }", null); 16 | Source source2 = new JavaSource("class m { }", null); 17 | 18 | Project prj = Project.builder().build(source); 19 | Project prj2 = Project.builder().build(source2); 20 | 21 | assertTrue(prj.enableCDS()); 22 | assertFalse(prj2.enableCDS()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/source/TestSourcesMutualDependency.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.source; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.io.IOException; 6 | import java.nio.file.Path; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | import dev.jbang.BaseTest; 11 | 12 | public class TestSourcesMutualDependency extends BaseTest { 13 | 14 | String classMain = "//SOURCES A.java\n" 15 | + "\n" 16 | + "public class Main { \n" 17 | + " public static void main(String args[]) {\n" 18 | + " new A();\n" 19 | + " }\n" 20 | + "}\n"; 21 | 22 | String classA = "//SOURCES B.java\n" 23 | + "\n" 24 | + "public class A {\n" 25 | + " public A() { new B(); }\n" 26 | + "}\n"; 27 | 28 | String classB = "//SOURCES A.java\n" 29 | + "\n" 30 | + "public class B {\n" 31 | + " public B() {\n" 32 | + " System.out.println(\"B constructor.\");\n" 33 | + " }\n" 34 | + "}\n"; 35 | 36 | @Test 37 | void testFindSourcesInMultipleFilesRecursively() throws IOException { 38 | Path mainPath = TestSource.createTmpFileWithContent("", "Main.java", classMain); 39 | TestSource.createTmpFileWithContent("", "A.java", classA); 40 | TestSource.createTmpFileWithContent("", "B.java", classB); 41 | String scriptURL = mainPath.toString(); 42 | Source source = Source.forResource(scriptURL, null); 43 | Project prj = Project.builder().build(source); 44 | assertEquals(3, prj.getMainSourceSet().getSources().size()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/util/NoOpUrlConnection.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import java.net.URL; 4 | import java.net.URLConnection; 5 | 6 | public class NoOpUrlConnection extends URLConnection { 7 | 8 | protected NoOpUrlConnection(URL url) { 9 | super(url); 10 | } 11 | 12 | @Override 13 | public void connect() { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/dev/jbang/util/TestTrustedSources.java: -------------------------------------------------------------------------------- 1 | package dev.jbang.util; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.io.IOException; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import dev.jbang.BaseTest; 10 | 11 | /** 12 | * Both class A and person.B have //SOURCES model/C.java 13 | */ 14 | public class TestTrustedSources extends BaseTest { 15 | 16 | @Test 17 | void testGoodUrlsToTrust() throws IOException { 18 | assertEquals("https://github.com/maxandersen/myproject/", 19 | Util.goodTrustURL("https://github.com/maxandersen/myproject/blob/master/file.java")); 20 | 21 | assertEquals("https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/", 22 | Util.goodTrustURL( 23 | "https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/2.0.0.Final/quarkus-cli-2.0.0.Final-runner.jar")); 24 | 25 | assertEquals("https://github.com/t.java", 26 | Util.goodTrustURL("https://github.com/t.java")); 27 | 28 | assertEquals("https://github.com/", 29 | Util.goodTrustURL("https://github.com/")); 30 | 31 | assertEquals("https://acme.org", 32 | Util.goodTrustURL("https://acme.org")); 33 | 34 | assertEquals("https://gist.github.com/maxandersen/", 35 | Util.goodTrustURL("https://gist.github.com/maxandersen/d4e465ab26ae5d85b7090aecf4003dc1")); 36 | 37 | assertEquals("https://gist.github.com/d4e465ab26ae5d85b7090aecf4003dc1", 38 | Util.goodTrustURL("https://gist.github.com/d4e465ab26ae5d85b7090aecf4003dc1")); 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/resources/allure.properties: -------------------------------------------------------------------------------- 1 | allure.results.directory=build/allure-results 2 | allure.label.tag = unit-test -------------------------------------------------------------------------------- /src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$ClassName --------------------------------------------------------------------------------