├── .asf.yaml
├── .git-blame-ignore-revs
├── .github
├── ISSUE_TEMPLATE
│ ├── BUG.yml
│ ├── FEATURE.yml
│ └── config.yml
├── dependabot.yml
├── pull_request_template.md
├── release-drafter.yml
└── workflows
│ ├── maven-verify.yml
│ ├── pr-automation.yml
│ ├── release-drafter.yml
│ └── stale.yml
├── .gitignore
├── Jenkinsfile
├── README.md
├── pom.xml
└── src
├── it
├── archive-dir
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── resources
│ │ │ └── jars
│ │ │ ├── excluded.jar
│ │ │ └── included.jar
│ └── verify.bsh
├── attachment-selection
│ ├── excluded.jar
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── resources
│ │ │ └── test.properties
│ └── verify.bsh
├── basic
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── Main.java
│ └── verify.bsh
├── keystore
├── resign
│ └── pom.xml
├── settings.xml
├── spacy path
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── Main.java
│ └── verify.bsh
├── type-detection
│ ├── jar-with-unusual.ext
│ ├── not-a-jar.properties
│ ├── pom.xml
│ ├── some.zip
│ ├── src
│ │ └── main
│ │ │ └── resources
│ │ │ └── test.properties
│ └── verify.bsh
├── unsign
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ ├── java
│ │ │ └── Main.java
│ │ │ └── resources
│ │ │ └── META-INF
│ │ │ ├── UNSIGNED.DSA
│ │ │ ├── UNSIGNED.RSA
│ │ │ └── UNSIGNED.SF
│ └── verify.bsh
├── verify-fail-if-not-signed
│ ├── invoker.properties
│ └── pom.xml
└── verify-fail
│ ├── invoker.properties
│ ├── pom.xml
│ └── tampered.jar
├── main
├── java
│ └── org
│ │ └── apache
│ │ └── maven
│ │ └── plugins
│ │ └── jarsigner
│ │ ├── AbstractJarsignerMojo.java
│ │ ├── JarsignerSignMojo.java
│ │ ├── JarsignerVerifyMojo.java
│ │ └── TsaSelector.java
└── resources
│ ├── META-INF
│ └── plexus
│ │ └── components.xml
│ ├── jarsigner.properties
│ ├── jarsigner_de.properties
│ ├── jarsigner_en.properties
│ └── jarsigner_fr.properties
├── site
├── apt
│ ├── examples
│ │ └── sign-and-verify-project.apt.vm
│ ├── index.apt.vm
│ └── usage.apt.vm
├── fml
│ └── faq.fml
├── resources
│ └── download.cgi
├── site.xml
└── xdoc
│ └── download.xml.vm
└── test
└── java
└── org
└── apache
└── maven
└── plugins
└── jarsigner
├── JarsignerSignMojoParallelTest.java
├── JarsignerSignMojoRetryTest.java
├── JarsignerSignMojoTest.java
├── JarsignerSignMojoTsaTest.java
├── JarsignerVerifyMojoTest.java
├── MojoTestCreator.java
├── PluginXmlParser.java
├── RequestMatchers.java
├── TestArtifacts.java
├── TestJavaToolResults.java
└── TsaSelectorTest.java
/.asf.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one or more
3 | # contributor license agreements. See the NOTICE file distributed with
4 | # this work for additional information regarding copyright ownership.
5 | # The ASF licenses this file to You under the Apache License, Version 2.0
6 | # (the "License"); you may not use this file except in compliance with
7 | # 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, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | # see https://s.apache.org/asfyaml
18 | github:
19 | description: "Apache Maven Jarsigner Plugin"
20 | homepage: https://maven.apache.org/plugins/maven-jarsigner-plugin/
21 | labels:
22 | - java
23 | - build-management
24 | - maven-plugins
25 | - maven-jarsigner-plugin
26 | - maven
27 | enabled_merge_buttons:
28 | squash: true
29 | merge: false
30 | rebase: true
31 | autolink_jira:
32 | - MJARSIGNER
33 | del_branch_on_merge: true
34 | features:
35 | issues: true
36 | notifications:
37 | commits: commits@maven.apache.org
38 | issues: issues@maven.apache.org
39 | pullrequests: issues@maven.apache.org
40 | jira_options: link label comment
41 |
--------------------------------------------------------------------------------
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
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 |
18 | # code reformat after parent 39
19 | 3a3c74cd3448452956f6e811384d26f9a32af43e
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG.yml:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one or more
3 | # contributor license agreements. See the NOTICE file distributed with
4 | # this work for additional information regarding copyright ownership.
5 | # The ASF licenses this file to You under the Apache License, Version 2.0
6 | # (the "License"); you may not use this file except in compliance with
7 | # 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, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
19 |
20 | name: Bug Report
21 | description: File a bug report
22 | labels: ["bug"]
23 |
24 | body:
25 | - type: markdown
26 | attributes:
27 | value: |
28 | Thanks for taking the time to fill out this bug report.
29 |
30 | Simple fixes in single PRs do not require issues.
31 |
32 | **Do you use the latest project version?**
33 |
34 | - type: input
35 | id: version
36 | attributes:
37 | label: Affected version
38 | validations:
39 | required: true
40 |
41 | - type: textarea
42 | id: message
43 | attributes:
44 | label: Bug description
45 | validations:
46 | required: true
47 |
48 |
49 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE.yml:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one or more
3 | # contributor license agreements. See the NOTICE file distributed with
4 | # this work for additional information regarding copyright ownership.
5 | # The ASF licenses this file to You under the Apache License, Version 2.0
6 | # (the "License"); you may not use this file except in compliance with
7 | # 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, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
19 |
20 | name: Feature request
21 | description: File a proposal for new feature, improvement
22 | labels: ["enhancement"]
23 |
24 | body:
25 | - type: markdown
26 | attributes:
27 | value: |
28 | Thanks for taking the time to fill out this new feature, improvement proposal.
29 |
30 | - type: textarea
31 | id: message
32 | attributes:
33 | label: New feature, improvement proposal
34 | validations:
35 | required: true
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one or more
3 | # contributor license agreements. See the NOTICE file distributed with
4 | # this work for additional information regarding copyright ownership.
5 | # The ASF licenses this file to You under the Apache License, Version 2.0
6 | # (the "License"); you may not use this file except in compliance with
7 | # 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, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | # https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
19 |
20 | blank_issues_enabled: false
21 |
22 | contact_links:
23 |
24 | - name: Project Mailing Lists
25 | url: https://maven.apache.org/mailing-lists.html
26 | about: Please ask a question or discuss here
27 |
28 | - name: Old JIRA Issues
29 | url: https://issues.apache.org/jira/projects/MJARSIGNER
30 | about: Please search old JIRA issues
31 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one or more
3 | # contributor license agreements. See the NOTICE file distributed with
4 | # this work for additional information regarding copyright ownership.
5 | # The ASF licenses this file to You under the Apache License, Version 2.0
6 | # (the "License"); you may not use this file except in compliance with
7 | # 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, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 | version: 2
18 | updates:
19 | - package-ecosystem: "maven"
20 | directory: "/"
21 | schedule:
22 | interval: "daily"
23 | - package-ecosystem: "github-actions"
24 | directory: "/"
25 | schedule:
26 | interval: "daily"
27 |
28 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Following this checklist to help us incorporate your
2 | contribution quickly and easily:
3 |
4 | - [ ] Your pull request should address just one issue, without pulling in other changes.
5 | - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
6 | - [ ] Each commit in the pull request should have a meaningful subject line and body.
7 | Note that commits might be squashed by a maintainer on merge.
8 | - [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied.
9 | This may not always be possible but is a best-practice.
10 | - [ ] Run `mvn verify` to make sure basic checks pass.
11 | A more thorough check will be performed on your pull request automatically.
12 | - [ ] You have run the integration tests successfully (`mvn -Prun-its verify`).
13 |
14 | If your pull request is about ~20 lines of code you don't need to sign an
15 | [Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf) if you are unsure
16 | please ask on the developers list.
17 |
18 | To make clear that you license your contribution under
19 | the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
20 | you have to acknowledge this by using the following check-box.
21 |
22 | - [ ] I hereby declare this contribution to be licenced under the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
23 | - [ ] In any other case, please file an [Apache Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
24 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
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 |
18 | _extends: maven-gh-actions-shared
19 |
--------------------------------------------------------------------------------
/.github/workflows/maven-verify.yml:
--------------------------------------------------------------------------------
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 |
18 | name: Verify
19 |
20 | on:
21 | push:
22 | pull_request:
23 |
24 | jobs:
25 | build:
26 | name: Verify
27 | uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4
28 |
--------------------------------------------------------------------------------
/.github/workflows/pr-automation.yml:
--------------------------------------------------------------------------------
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 |
18 | name: PR Automation
19 | on:
20 | pull_request_target:
21 | types:
22 | - closed
23 |
24 | jobs:
25 | pr-automation:
26 | name: PR Automation
27 | uses: apache/maven-gh-actions-shared/.github/workflows/pr-automation.yml@v4
28 |
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
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 |
18 | name: Release Drafter
19 | on:
20 | push:
21 | branches:
22 | - master
23 | workflow_dispatch:
24 |
25 | jobs:
26 | update_release_draft:
27 | uses: apache/maven-gh-actions-shared/.github/workflows/release-drafter.yml@v4
28 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
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 |
18 | name: Stale
19 |
20 | on:
21 | schedule:
22 | - cron: '47 0 * * *'
23 | issue_comment:
24 | types: [ 'created' ]
25 |
26 | jobs:
27 | stale:
28 | uses: 'apache/maven-gh-actions-shared/.github/workflows/stale.yml@v4'
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .project
3 | .classpath
4 | .settings/
5 | .svn/
6 | bin/
7 | # Intellij
8 | *.ipr
9 | *.iml
10 | .idea
11 | out/
12 | .DS_Store
13 | /bootstrap
14 | /dependencies.xml
15 | .java-version
16 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | asfMavenTlpPlgnBuild()
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
17 | Contributing to [Apache Maven Jarsigner Plugin](https://maven.apache.org/plugins/maven-jarsigner-plugin/)
18 | ======================
19 |
20 | [][license]
21 | [](https://search.maven.org/artifact/org.apache.maven.plugins/maven-jarsigner-plugin)
22 | [](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/apache/maven/plugins/maven-jarsigner-plugin/README.md)
23 | [][build]
24 | [][test-results]
25 |
26 |
27 | You have found a bug, or you have an idea for a cool new feature? Contributing
28 | code is a great way to give something back to the open source community. Before
29 | you dig right into the code, there are a few guidelines that we need
30 | contributors to follow so that we can have a chance of keeping on top of
31 | things.
32 |
33 | Getting Started
34 | ---------------
35 |
36 | + Make sure you have a [GitHub account](https://github.com/signup/free).
37 | + If you're planning to implement a new feature, it makes sense to discuss your changes
38 | on the [dev list][ml-list] first.
39 | This way you can make sure you're not wasting your time on something that isn't
40 | considered to be in Apache Maven's scope.
41 | + Submit a ticket for your issue, assuming one does not already exist.
42 | + Clearly describe the issue, including steps to reproduce when it is a bug.
43 | + Make sure you fill in the earliest version that you know has the issue.
44 | + Fork the repository on GitHub.
45 |
46 | Making and Submitting Changes
47 | --------------
48 |
49 | We accept Pull Requests via GitHub. The [developer mailing list][ml-list] is the
50 | main channel of communication for contributors.
51 | There are some guidelines which will make applying PRs easier for us:
52 | + Create a topic branch from where you want to base your work (this is usually the master branch).
53 | Push your changes to a topic branch in your fork of the repository.
54 | + Make commits of logical units.
55 | + Respect the original code style: by using the same [codestyle][code-style],
56 | patches should only highlight the actual difference, not being disturbed by any formatting issues:
57 | + Only use spaces for indentation.
58 | + Create minimal diffs - disable on save actions like reformat source code or organize imports.
59 | If you feel the source code should be reformatted, create a separate PR for this change.
60 | + Check for unnecessary whitespace with `git diff --check` before committing.
61 | + Make sure you have added the necessary tests (JUnit/IT) for your changes.
62 | + Run all the tests with `mvn -Prun-its verify` to assure nothing else was accidentally broken.
63 | + Submit a pull request to the repository in the Apache organization.
64 |
65 | If you plan to contribute on a regular basis, please consider filing a [contributor license agreement][cla].
66 |
67 | Additional Resources
68 | --------------------
69 |
70 | + [Contributing patches](https://maven.apache.org/guides/development/guide-maven-development.html#Creating_and_submitting_a_patch)
71 | + [Contributor License Agreement][cla]
72 | + [General GitHub documentation](https://help.github.com/)
73 | + [GitHub pull request documentation](https://help.github.com/send-pull-requests/)
74 | + [Apache Maven X Account](https://x.com/ASFMavenProject)
75 | + [Apache Maven Bluesky Account](https://bsky.app/profile/maven.apache.org)
76 | + [Apache Maven Mastodon Account](https://mastodon.social/deck/@ASFMavenProject@fosstodon.org)
77 |
78 | [license]: https://www.apache.org/licenses/LICENSE-2.0
79 | [ml-list]: https://maven.apache.org/mailing-lists.html
80 | [code-style]: https://maven.apache.org/developers/conventions/code.html
81 | [cla]: https://www.apache.org/licenses/#clas
82 | [maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index
83 | [test-results]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-jarsigner-plugin/job/master/lastCompletedBuild/testReport/
84 | [build]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-jarsigner-plugin/job/master/
85 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 | 4.0.0
22 |
23 |
24 | org.apache.maven.plugins
25 | maven-plugins
26 | 43
27 |
28 |
29 |
30 | maven-jarsigner-plugin
31 | 3.1.1-SNAPSHOT
32 | maven-plugin
33 |
34 | Apache Maven Jarsigner Plugin
35 | Signs or verifies a project artifact and attachments using jarsigner.
36 |
37 |
38 |
39 | Christian Schulte
40 |
41 |
42 | Jerome Lacube
43 |
44 |
45 |
46 |
47 | ${mavenVersion}
48 |
49 |
50 |
51 | scm:git:https://gitbox.apache.org/repos/asf/maven-jarsigner-plugin.git
52 | scm:git:https://gitbox.apache.org/repos/asf/maven-jarsigner-plugin.git
53 | HEAD
54 | https://github.com/apache/maven-jarsigner-plugin/tree/${project.scm.tag}
55 |
56 |
57 | GitHub Issues
58 | https://github.com/apache/maven-jarsigner-plugin/issues
59 |
60 |
61 | Jenkins
62 | https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-jarsigner-plugin/
63 |
64 |
65 |
66 | apache.website
67 | scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}
68 |
69 |
70 |
71 |
72 | 3.6.3
73 | 0.8.12
74 | 2024-09-03T16:36:13Z
75 |
76 |
77 |
78 |
79 | org.apache.maven
80 | maven-plugin-api
81 | ${mavenVersion}
82 | provided
83 |
84 |
85 | org.apache.maven
86 | maven-core
87 | ${mavenVersion}
88 | provided
89 |
90 |
91 | org.apache.maven
92 | maven-artifact
93 | ${mavenVersion}
94 | provided
95 |
96 |
97 | org.apache.maven
98 | maven-settings
99 | ${mavenVersion}
100 | provided
101 |
102 |
103 | org.apache.maven.plugin-tools
104 | maven-plugin-annotations
105 | provided
106 |
107 |
108 | org.apache.maven.shared
109 | maven-shared-utils
110 | 3.4.2
111 |
112 |
113 | org.sonatype.plexus
114 | plexus-sec-dispatcher
115 | 1.4
116 | compile
117 |
118 |
119 | org.apache.maven.shared
120 | maven-jarsigner
121 | 3.1.0
122 |
123 |
124 | javax.inject
125 | javax.inject
126 | 1
127 | provided
128 |
129 |
130 | junit
131 | junit
132 | 4.13.2
133 | test
134 |
135 |
136 | org.slf4j
137 | slf4j-api
138 | 1.7.36
139 | test
140 |
141 |
142 |
143 | org.slf4j
144 | slf4j-simple
145 | 1.7.36
146 | test
147 |
148 |
149 | org.mockito
150 | mockito-core
151 | 4.11.0
152 | test
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | org.apache.rat
162 | apache-rat-plugin
163 |
164 |
165 |
168 | src/it/unsign/src/main/resources/META-INF/UNSIGNED.*
169 | src/it/keystore
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | org.jacoco
178 | jacoco-maven-plugin
179 | ${jacocoVersion}
180 |
181 |
182 |
183 | prepare-agent
184 |
185 |
186 |
187 | report
188 |
189 | report
190 |
191 | prepare-package
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 | run-its
201 |
202 |
203 |
204 |
205 | org.apache.maven.plugins
206 | maven-invoker-plugin
207 |
208 |
209 | clean
210 | verify
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
--------------------------------------------------------------------------------
/src/it/archive-dir/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the signing of multiple JARs within a directory selected by includes/excludes.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-surefire-plugin
58 | 2.3.1
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jarsigner-plugin
63 | @project.version@
64 |
65 | test-01
66 | key-passwd
67 | TESTING
68 | false
69 | target/classes/jars
70 |
71 | excluded.jar
72 |
73 |
74 |
75 |
76 | sign-jars
77 |
78 | sign
79 |
80 |
81 |
82 | verify-jars
83 |
84 | verify
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/it/archive-dir/src/main/resources/jars/excluded.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/archive-dir/src/main/resources/jars/excluded.jar
--------------------------------------------------------------------------------
/src/it/archive-dir/src/main/resources/jars/included.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/archive-dir/src/main/resources/jars/included.jar
--------------------------------------------------------------------------------
/src/it/archive-dir/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.jar.*;
22 |
23 | File jarDir = new File( basedir, "target/classes/jars" );
24 |
25 | File includedJarFile = new File( jarDir, "included.jar" );
26 | System.out.println( "Checking for existence of " + includedJarFile );
27 | if ( !includedJarFile.isFile() )
28 | {
29 | throw new Exception( "missing " + includedJarFile );
30 | }
31 |
32 | JarFile includedJar = new JarFile( includedJarFile );
33 | System.out.println( "Checking for existence of " + includedJarFile.getName() + "!/META-INF/TESTING.SF" );
34 | if ( includedJar.getEntry( "META-INF/TESTING.SF" ) == null )
35 | {
36 | throw new Exception( "missing " + includedJarFile.getName() + "!/META-INF/TESTING.SF" );
37 | }
38 | System.out.println( "Checking for existence of " + includedJarFile.getName() + "!/META-INF/TESTING.DSA" );
39 | if ( includedJar.getEntry( "META-INF/TESTING.DSA" ) == null )
40 | {
41 | throw new Exception( "missing " + includedJarFile.getName() + "!/META-INF/TESTING.DSA" );
42 | }
43 | includedJar.close();
44 |
45 | File excludedJarFile = new File( jarDir, "excluded.jar" );
46 | System.out.println( "Checking for existence of " + excludedJarFile );
47 | if ( !excludedJarFile.isFile() )
48 | {
49 | throw new Exception( "missing " + excludedJarFile );
50 | }
51 |
52 | JarFile excludedJar = new JarFile( excludedJarFile );
53 | System.out.println( "Checking for absence of " + excludedJarFile.getName() + "!/META-INF/TESTING.SF" );
54 | if ( excludedJar.getEntry( "META-INF/TESTING.SF" ) != null )
55 | {
56 | throw new Exception( "present " + excludedJarFile.getName() + "!/META-INF/TESTING.SF" );
57 | }
58 | System.out.println( "Checking for absence of " + excludedJarFile.getName() + "!/META-INF/TESTING.DSA" );
59 | if ( excludedJar.getEntry( "META-INF/TESTING.DSA" ) != null )
60 | {
61 | throw new Exception( "present " + excludedJarFile.getName() + "!/META-INF/TESTING.DSA" );
62 | }
63 | excludedJar.close();
64 |
65 | return true;
66 |
--------------------------------------------------------------------------------
/src/it/attachment-selection/excluded.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/attachment-selection/excluded.jar
--------------------------------------------------------------------------------
/src/it/attachment-selection/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the selection of specific attachments.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.codehaus.mojo
57 | build-helper-maven-plugin
58 | 1.2
59 |
60 |
61 | attach-artifacts
62 |
63 | attach-artifact
64 |
65 |
66 |
67 |
68 | excluded.jar
69 | jar
70 | unsigned
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | org.apache.maven.plugins
79 | maven-surefire-plugin
80 | 2.3.1
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-jarsigner-plugin
85 | @project.version@
86 |
87 | test-01
88 | key-passwd
89 | TESTING
90 |
91 | unsigned
92 |
93 |
94 |
95 |
96 | sign-jars
97 |
98 | sign
99 |
100 |
101 |
102 | verify-jars
103 |
104 | verify
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/src/it/attachment-selection/src/main/resources/test.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 |
18 | key = value
--------------------------------------------------------------------------------
/src/it/attachment-selection/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.zip.*;
22 |
23 | File attachedJarFile = new File( basedir, "excluded.jar" );
24 | System.out.println( "Checking for existence of " + attachedJarFile );
25 | if ( !attachedJarFile.isFile() )
26 | {
27 | throw new Exception( "missing " + attachedJarFile );
28 | }
29 |
30 | ZipFile attachedJar = new ZipFile( attachedJarFile );
31 | System.out.println( "Checking for absence of " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
32 | if ( attachedJar.getEntry( "META-INF/TESTING.SF" ) != null )
33 | {
34 | throw new Exception( "present " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
35 | }
36 | System.out.println( "Checking for absence of " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
37 | if ( attachedJar.getEntry( "META-INF/TESTING.DSA" ) != null )
38 | {
39 | throw new Exception( "present " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
40 | }
41 | attachedJar.close();
42 |
43 | return true;
44 |
--------------------------------------------------------------------------------
/src/it/basic/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the signing of a simple JAR.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-source-plugin
58 | 2.0.4
59 |
60 |
61 | attach-sources
62 |
63 | jar
64 |
65 |
66 |
67 |
68 |
69 | org.apache.maven.plugins
70 | maven-surefire-plugin
71 | 2.3.1
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-jarsigner-plugin
76 | @project.version@
77 |
78 | test-01
79 | key-passwd
80 | TESTING
81 |
82 |
83 |
84 | sign-jars
85 |
86 | sign
87 |
88 |
89 |
90 | verify-jars
91 |
92 | verify
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/src/it/basic/src/main/java/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | /**
21 | * Application entry point.
22 | */
23 | public class Main
24 | {
25 | }
26 |
--------------------------------------------------------------------------------
/src/it/basic/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.jar.*;
22 |
23 | File targetDir = new File( basedir, "target" );
24 |
25 | File mainJarFile = new File( targetDir, "test-1.0.jar" );
26 | System.out.println( "Checking for existence of " + mainJarFile );
27 | if ( !mainJarFile.isFile() )
28 | {
29 | throw new Exception( "missing " + mainJarFile );
30 | }
31 |
32 | JarFile mainJar = new JarFile( mainJarFile );
33 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
34 | if ( mainJar.getEntry( "META-INF/TESTING.SF" ) == null )
35 | {
36 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
37 | }
38 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
39 | if ( mainJar.getEntry( "META-INF/TESTING.DSA" ) == null )
40 | {
41 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
42 | }
43 | mainJar.close();
44 |
45 | File attachedJarFile = new File( targetDir, "test-1.0-sources.jar" );
46 | System.out.println( "Checking for existence of " + attachedJarFile );
47 | if ( !attachedJarFile.isFile() )
48 | {
49 | throw new Exception( "missing " + attachedJarFile );
50 | }
51 |
52 | JarFile attachedJar = new JarFile( attachedJarFile );
53 | System.out.println( "Checking for existence of " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
54 | if ( attachedJar.getEntry( "META-INF/TESTING.SF" ) == null )
55 | {
56 | throw new Exception( "missing " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
57 | }
58 | System.out.println( "Checking for existence of " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
59 | if ( attachedJar.getEntry( "META-INF/TESTING.DSA" ) == null )
60 | {
61 | throw new Exception( "missing " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
62 | }
63 | attachedJar.close();
64 |
65 | return true;
66 |
--------------------------------------------------------------------------------
/src/it/keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/keystore
--------------------------------------------------------------------------------
/src/it/resign/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 | 4.0.0
23 |
24 | org.apache.maven.its.jarsigner
25 | test
26 | 1.0
27 | jar
28 |
29 |
30 | Tests the signing of an already signed JAR (see https://issues.apache.org/jira/browse/MJARSIGNER-33) that should be unsigned before re-signing.
31 |
32 |
33 |
34 | true
35 |
36 |
37 |
38 |
39 | org.swinglabs
40 | jxlayer
41 | 3.0.4
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-compiler-plugin
50 | 2.0.2
51 |
52 |
53 | org.apache.maven.plugins
54 | maven-jar-plugin
55 | 2.1
56 |
57 |
58 | org.apache.maven.plugins
59 | maven-resources-plugin
60 | 2.2
61 |
62 |
63 | org.apache.maven.plugins
64 | maven-dependency-plugin
65 | 2.8
66 |
67 |
68 |
69 | copy-dependencies
70 |
71 |
72 | ${project.build.directory}/deps
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | org.apache.maven.plugins
81 | maven-surefire-plugin
82 | 2.3.1
83 |
84 |
85 | org.apache.maven.plugins
86 | maven-jarsigner-plugin
87 | @project.version@
88 |
89 | test-01
90 | key-passwd
91 | TESTING
92 | true
93 | ${project.build.directory}/deps/jxlayer-3.0.4.jar
94 |
95 |
96 |
97 | sign-jars
98 |
99 | sign
100 |
101 |
102 |
103 | verify-jars
104 |
105 | verify
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/src/it/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
24 |
25 | it-repo
26 |
27 | true
28 |
29 |
30 |
34 | @project.basedir@/src/it/keystore
35 | store-passwd
36 |
37 |
38 |
39 | local.central
40 | @localRepositoryUrl@
41 |
42 | true
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 |
51 | local.central
52 | @localRepositoryUrl@
53 |
54 | true
55 |
56 |
57 | true
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/it/spacy path/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the invocation of the jarsigner tool when paths with spaces are involved.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-surefire-plugin
58 | 2.3.1
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jarsigner-plugin
63 | @project.version@
64 |
65 | test-01
66 | key-passwd
67 | TESTING
68 |
69 |
70 |
71 | sign-jars
72 |
73 | sign
74 |
75 |
76 |
77 | verify-jars
78 |
79 | verify
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/it/spacy path/src/main/java/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | /**
21 | * Application entry point.
22 | */
23 | public class Main
24 | {
25 | }
26 |
--------------------------------------------------------------------------------
/src/it/spacy path/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.jar.*;
22 |
23 | File targetDir = new File( basedir, "target" );
24 |
25 | File mainJarFile = new File( targetDir, "test-1.0.jar" );
26 | System.out.println( "Checking for existence of " + mainJarFile );
27 | if ( !mainJarFile.isFile() )
28 | {
29 | throw new Exception( "missing " + mainJarFile );
30 | }
31 |
32 | JarFile mainJar = new JarFile( mainJarFile );
33 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
34 | if ( mainJar.getEntry( "META-INF/TESTING.SF" ) == null )
35 | {
36 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
37 | }
38 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
39 | if ( mainJar.getEntry( "META-INF/TESTING.DSA" ) == null )
40 | {
41 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
42 | }
43 | mainJar.close();
44 |
45 | return true;
46 |
--------------------------------------------------------------------------------
/src/it/type-detection/jar-with-unusual.ext:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/type-detection/jar-with-unusual.ext
--------------------------------------------------------------------------------
/src/it/type-detection/not-a-jar.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 |
--------------------------------------------------------------------------------
/src/it/type-detection/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the detection of JAR/ZIP files (we don't want to sign/verify other file formats).
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.codehaus.mojo
57 | build-helper-maven-plugin
58 | 1.2
59 |
60 |
61 | attach-artifacts
62 |
63 | attach-artifact
64 |
65 |
66 |
67 |
68 |
72 | jar-with-unusual.ext
73 | foo
74 | a
75 |
76 |
77 | not-a-jar.properties
78 | bar
79 | b
80 |
81 |
82 |
83 | some.zip
84 | zip
85 | c
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.apache.maven.plugins
94 | maven-surefire-plugin
95 | 2.3.1
96 |
97 |
98 | org.apache.maven.plugins
99 | maven-jarsigner-plugin
100 | @project.version@
101 |
102 | test-01
103 | key-passwd
104 | TESTING
105 |
106 |
107 |
108 | sign-jars
109 |
110 | sign
111 |
112 |
113 |
114 | verify-jars
115 |
116 | verify
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/src/it/type-detection/some.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/type-detection/some.zip
--------------------------------------------------------------------------------
/src/it/type-detection/src/main/resources/test.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 |
18 | key = value
--------------------------------------------------------------------------------
/src/it/type-detection/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.zip.*;
22 |
23 | File attachedJarFile = new File( basedir, "jar-with-unusual.ext" );
24 | System.out.println( "Checking for existence of " + attachedJarFile );
25 | if ( !attachedJarFile.isFile() )
26 | {
27 | throw new Exception( "missing " + attachedJarFile );
28 | }
29 |
30 | ZipFile attachedJar = new ZipFile( attachedJarFile );
31 | System.out.println( "Checking for existence of " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
32 | if ( attachedJar.getEntry( "META-INF/TESTING.SF" ) == null )
33 | {
34 | throw new Exception( "missing " + attachedJarFile.getName() + "!/META-INF/TESTING.SF" );
35 | }
36 | System.out.println( "Checking for existence of " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
37 | if ( attachedJar.getEntry( "META-INF/TESTING.DSA" ) == null )
38 | {
39 | throw new Exception( "missing " + attachedJarFile.getName() + "!/META-INF/TESTING.DSA" );
40 | }
41 | attachedJar.close();
42 |
43 | File attachedZipFile = new File( basedir, "some.zip" );
44 | System.out.println( "Checking for existence of " + attachedZipFile );
45 | if ( !attachedZipFile.isFile() )
46 | {
47 | throw new Exception( "missing " + attachedZipFile );
48 | }
49 |
50 | ZipFile attachedZip = new ZipFile( attachedZipFile );
51 | System.out.println( "Checking for existence of " + attachedZipFile.getName() + "!/META-INF/TESTING.SF" );
52 | if ( attachedZip.getEntry( "META-INF/TESTING.SF" ) == null )
53 | {
54 | throw new Exception( "missing " + attachedZipFile.getName() + "!/META-INF/TESTING.SF" );
55 | }
56 | System.out.println( "Checking for existence of " + attachedZipFile.getName() + "!/META-INF/TESTING.DSA" );
57 | if ( attachedZip.getEntry( "META-INF/TESTING.DSA" ) == null )
58 | {
59 | throw new Exception( "missing " + attachedZipFile.getName() + "!/META-INF/TESTING.DSA" );
60 | }
61 | attachedZip.close();
62 |
63 | return true;
64 |
--------------------------------------------------------------------------------
/src/it/unsign/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests the signing of an already signed JAR that should be unsigned before re-signing.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-surefire-plugin
58 | 2.3.1
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jarsigner-plugin
63 | @project.version@
64 |
65 | test-01
66 | key-passwd
67 | TESTING
68 | true
69 |
70 |
71 |
72 | sign-jars
73 |
74 | sign
75 |
76 |
77 |
78 | verify-jars
79 |
80 | verify
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/it/unsign/src/main/java/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | /**
21 | * Application entry point.
22 | */
23 | public class Main
24 | {
25 | }
26 |
--------------------------------------------------------------------------------
/src/it/unsign/src/main/resources/META-INF/UNSIGNED.DSA:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/unsign/src/main/resources/META-INF/UNSIGNED.DSA
--------------------------------------------------------------------------------
/src/it/unsign/src/main/resources/META-INF/UNSIGNED.RSA:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/unsign/src/main/resources/META-INF/UNSIGNED.RSA
--------------------------------------------------------------------------------
/src/it/unsign/src/main/resources/META-INF/UNSIGNED.SF:
--------------------------------------------------------------------------------
1 | Signature-Version: 1.0
2 | Created-By: 1.4.2_16 (Sun Microsystems Inc.)
3 | SHA1-Digest-Manifest: gTrf1t9RIQNLDAEO4n3ikaxAoIg=
4 |
5 | Name: Main.java
6 | SHA1-Digest: b+ff3QfBH9heex9FQjrfgsATWVc=
7 |
8 |
--------------------------------------------------------------------------------
/src/it/unsign/verify.bsh:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import java.io.*;
21 | import java.util.jar.*;
22 |
23 | File targetDir = new File( basedir, "target" );
24 |
25 | File mainJarFile = new File( targetDir, "test-1.0.jar" );
26 | System.out.println( "Checking for existence of " + mainJarFile );
27 | if ( !mainJarFile.isFile() )
28 | {
29 | throw new Exception( "missing " + mainJarFile );
30 | }
31 |
32 | JarFile mainJar = new JarFile( mainJarFile );
33 |
34 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
35 | if ( mainJar.getEntry( "META-INF/TESTING.SF" ) == null )
36 | {
37 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.SF" );
38 | }
39 |
40 | System.out.println( "Checking for existence of " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
41 | if ( mainJar.getEntry( "META-INF/TESTING.DSA" ) == null )
42 | {
43 | throw new Exception( "missing " + mainJarFile.getName() + "!/META-INF/TESTING.DSA" );
44 | }
45 |
46 | System.out.println( "Checking for absence of " + mainJarFile.getName() + "!/META-INF/UNSIGNED.SF" );
47 | if ( mainJar.getEntry( "META-INF/UNSIGNED.SF" ) != null )
48 | {
49 | throw new Exception( "present " + mainJarFile.getName() + "!/META-INF/UNSIGNED.SF" );
50 | }
51 |
52 | System.out.println( "Checking for absence of " + mainJarFile.getName() + "!/META-INF/UNSIGNED.DSA" );
53 | if ( mainJar.getEntry( "META-INF/UNSIGNED.DSA" ) != null )
54 | {
55 | throw new Exception( "present " + mainJarFile.getName() + "!/META-INF/UNSIGNED.DSA" );
56 | }
57 |
58 | System.out.println( "Checking for absence of " + mainJarFile.getName() + "!/META-INF/UNSIGNED.RSA" );
59 | if ( mainJar.getEntry( "META-INF/UNSIGNED.RSA" ) != null )
60 | {
61 | throw new Exception( "present " + mainJarFile.getName() + "!/META-INF/UNSIGNED.RSA" );
62 | }
63 |
64 | mainJar.close();
65 |
66 | return true;
67 |
--------------------------------------------------------------------------------
/src/it/verify-fail-if-not-signed/invoker.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 |
18 | invoker.buildResult = failure
19 |
--------------------------------------------------------------------------------
/src/it/verify-fail-if-not-signed/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 |
29 |
30 | Tests that verification of a none signed JAR fails when having the errorWhenNotsigned flag to true (see MJARSIGNED-18).
31 |
32 |
33 |
34 | true
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-surefire-plugin
58 | 2.3.1
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jarsigner-plugin
63 | @project.version@
64 |
65 | true
66 |
67 |
68 |
69 | verify-archive
70 |
71 | verify
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/it/verify-fail/invoker.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 |
18 | invoker.buildResult = failure
19 |
--------------------------------------------------------------------------------
/src/it/verify-fail/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 | 4.0.0
24 |
25 | org.apache.maven.its.jarsigner
26 | test
27 | 1.0
28 | jar
29 |
30 |
31 | Tests that verification of a tampared JAR fails.
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 | 2.0.2
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-jar-plugin
48 | 2.1
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-resources-plugin
53 | 2.2
54 |
55 |
56 | org.apache.maven.plugins
57 | maven-surefire-plugin
58 | 2.3.1
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jarsigner-plugin
63 | @project.version@
64 |
65 | tampered.jar
66 |
93 |
94 |
95 |
96 | verify-archive
97 |
98 | verify
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/it/verify-fail/tampered.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apache/maven-jarsigner-plugin/48c135e902b77a603ce38e8f899f841c2c568445/src/it/verify-fail/tampered.jar
--------------------------------------------------------------------------------
/src/main/java/org/apache/maven/plugins/jarsigner/JarsignerSignMojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import javax.inject.Inject;
22 | import javax.inject.Named;
23 |
24 | import java.io.File;
25 | import java.io.IOException;
26 | import java.time.Duration;
27 | import java.util.List;
28 | import java.util.concurrent.Callable;
29 | import java.util.concurrent.ExecutionException;
30 | import java.util.concurrent.ExecutorService;
31 | import java.util.concurrent.Executors;
32 | import java.util.concurrent.Future;
33 | import java.util.stream.Collectors;
34 |
35 | import org.apache.maven.plugin.MojoExecutionException;
36 | import org.apache.maven.plugins.annotations.LifecyclePhase;
37 | import org.apache.maven.plugins.annotations.Mojo;
38 | import org.apache.maven.plugins.annotations.Parameter;
39 | import org.apache.maven.plugins.jarsigner.TsaSelector.TsaServer;
40 | import org.apache.maven.shared.jarsigner.JarSigner;
41 | import org.apache.maven.shared.jarsigner.JarSignerRequest;
42 | import org.apache.maven.shared.jarsigner.JarSignerSignRequest;
43 | import org.apache.maven.shared.jarsigner.JarSignerUtil;
44 | import org.apache.maven.shared.utils.StringUtils;
45 | import org.apache.maven.shared.utils.cli.Commandline;
46 | import org.apache.maven.shared.utils.cli.javatool.JavaToolException;
47 | import org.apache.maven.shared.utils.cli.javatool.JavaToolResult;
48 | import org.apache.maven.toolchain.ToolchainManager;
49 | import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
50 |
51 | /**
52 | * Signs a project artifact and attachments using jarsigner.
53 | *
54 | * @author Christian Schulte
55 | * @since 1.0
56 | */
57 | @Mojo(name = "sign", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true)
58 | public class JarsignerSignMojo extends AbstractJarsignerMojo {
59 |
60 | /**
61 | * See options.
62 | */
63 | @Parameter(property = "jarsigner.keypass")
64 | private String keypass;
65 |
66 | /**
67 | * See options.
68 | */
69 | @Parameter(property = "jarsigner.sigfile")
70 | private String sigfile;
71 |
72 | /**
73 | * Indicates whether existing signatures should be removed from the processed JAR files prior to signing them. If
74 | * enabled, the resulting JAR will appear as being signed only once.
75 | *
76 | * @since 1.1
77 | */
78 | @Parameter(property = "jarsigner.removeExistingSignatures", defaultValue = "false")
79 | private boolean removeExistingSignatures;
80 |
81 | /**
82 | *
URL(s) to Time Stamping Authority (TSA) server(s) to use to timestamp the signing.
83 | * See options.
84 | * Separate multiple TSA URLs with comma (without space) or a nested XML tag.
85 | *
86 | * {@code
87 | *
88 | * http://timestamp.digicert.com,http://timestamp.globalsign.com/tsa/r6advanced1
89 | *
90 | * }
91 | *
92 | * {@code
93 | *
94 | *
95 | * http://timestamp.digicert.com
96 | * http://timestamp.globalsign.com/tsa/r6advanced1
97 | *
98 | *
99 | * }
100 | *
101 | * Usage of multiple TSA servers only makes sense when {@link #maxTries} is more than 1. A different TSA server
102 | * will only be used at retries.
103 | *
104 | * Changed to a list since 3.1.0. Single XML element (without comma) is still supported.
105 | *
106 | * @since 1.3
107 | */
108 | @Parameter(property = "jarsigner.tsa")
109 | private String[] tsa;
110 |
111 | /**
112 | * Alias(es) for certificate(s) in the active keystore used to find a TSA URL. From the certificate the X509v3
113 | * extension "Subject Information Access" field is examined to find the TSA server URL. See
114 | * options.
115 | * Separate multiple aliases with comma (without space) or a nested XML tag.
116 | *
117 | * {@code
118 | *
119 | * alias1,alias2
120 | *
121 | * }
122 | *
123 | * {@code
124 | *
125 | *
126 | * alias1
127 | * alias2
128 | *
129 | *
130 | * }
131 | *
132 | * Should not be used at the same time as the {@link #tsa} parameter (because jarsigner will typically ignore
133 | * tsacert, if tsa is set).
134 | *
135 | * Usage of multiple aliases only makes sense when {@link #maxTries} is more than 1. A different TSA server
136 | * will only be used at retries.
137 | *
138 | * Changed to a list since 3.1.0. Single XML element (without comma) is still supported.
139 | *
140 | * @since 1.3
141 | */
142 | @Parameter(property = "jarsigner.tsacert")
143 | private String[] tsacert;
144 |
145 | /**
146 | * OID(s) to send to the TSA server to identify the policy ID the server should use. If not specified TSA server
147 | * will choose a default policy ID. Each TSA server vendor will typically define their own policy OIDs. See
148 | * options.
149 | * Separate multiple OIDs with comma (without space) or a nested XML tag.
150 | *
151 | * {@code
152 | *
153 | * 1.3.6.1.4.1.4146.2.3.1.2,2.16.840.1.114412.7.1
154 | *
155 | * }
156 | *
157 | * {@code
158 | *
159 | *
160 | * 1.3.6.1.4.1.4146.2.3.1.2
161 | * 2.16.840.1.114412.7.1
162 | *
163 | *
164 | * }
165 | *
166 | * If used, the number of OIDs should be the same as the number of elements in {@link #tsa} or {@link #tsacert}.
167 | * The first OID will be used for the first TSA server, the second OID for the second TSA server and so on.
168 | *
169 | * @since 3.1.0
170 | */
171 | @Parameter(property = "jarsigner.tsapolicyid")
172 | private String[] tsapolicyid;
173 |
174 | /**
175 | * The message digest algorithm to use in the messageImprint that the TSA server will timestamp. A default value
176 | * (for example {@code SHA-384}) will be selected by jarsigner if this parameter is not set. Only available in
177 | * Java 11 and later. See options.
178 | *
179 | * @since 3.1.0
180 | */
181 | @Parameter(property = "jarsigner.tsadigestalg")
182 | private String tsadigestalg;
183 |
184 | /**
185 | * Location of the extra certificate chain file. See
186 | * options.
187 | *
188 | * @since 1.5
189 | */
190 | @Parameter(property = "jarsigner.certchain", required = false)
191 | private File certchain;
192 |
193 | /**
194 | * How many times to try to sign a jar (assuming each previous attempt is a failure). This option may be desirable
195 | * if any network operations are used during signing, for example using a Time Stamp Authority or network based
196 | * PKCS11 HSM solution for storing code signing keys.
197 | *
198 | * The default value of 1 indicates that no retries should be made.
199 | *
200 | * @since 3.1.0
201 | */
202 | @Parameter(property = "jarsigner.maxTries", defaultValue = "1")
203 | private int maxTries;
204 |
205 | /**
206 | * Maximum delay, in seconds, to wait after a failed attempt before re-trying. The delay after a failed attempt
207 | * follows an exponential backoff strategy, with increasing delay times.
208 | *
209 | * @since 3.1.0
210 | */
211 | @Parameter(property = "jarsigner.maxRetryDelaySeconds", defaultValue = "0")
212 | private int maxRetryDelaySeconds;
213 |
214 | /**
215 | * Maximum number of parallel threads to use when signing jar files. Increases performance when signing multiple jar
216 | * files, especially when network operations are used during signing, for example when using a Time Stamp Authority
217 | * or network based PKCS11 HSM solution for storing code signing keys. Note: the logging from the signing process
218 | * will be interleaved, and harder to read, when using many threads.
219 | *
220 | * @since 3.1.0
221 | */
222 | @Parameter(property = "jarsigner.threadCount", defaultValue = "1")
223 | private int threadCount;
224 |
225 | /** Current WaitStrategy, to allow for sleeping after a signing failure. */
226 | private WaitStrategy waitStrategy = this::defaultWaitStrategy;
227 |
228 | private TsaSelector tsaSelector;
229 |
230 | /** Exponent limit for exponential wait after failure function. 2^20 = 1048576 sec ~= 12 days. */
231 | private static final int MAX_WAIT_EXPONENT_ATTEMPT = 20;
232 |
233 | @Inject
234 | public JarsignerSignMojo(
235 | JarSigner jarSigner,
236 | ToolchainManager toolchainManager,
237 | @Named("mng-4384") SecDispatcher securityDispatcher) {
238 | super(jarSigner, toolchainManager, securityDispatcher);
239 | }
240 |
241 | // for testing; invoked via reflection
242 | JarsignerSignMojo() {
243 | super(null, null, null);
244 | }
245 |
246 | @Override
247 | protected String getCommandlineInfo(final Commandline commandLine) {
248 | String commandLineInfo = commandLine != null ? commandLine.toString() : null;
249 |
250 | if (commandLineInfo != null) {
251 | commandLineInfo = StringUtils.replace(commandLineInfo, this.keypass, "'*****'");
252 | }
253 |
254 | return commandLineInfo;
255 | }
256 |
257 | @Override
258 | protected void preProcessArchive(final File archive) throws MojoExecutionException {
259 | if (removeExistingSignatures) {
260 | try {
261 | JarSignerUtil.unsignArchive(archive);
262 | } catch (IOException e) {
263 | throw new MojoExecutionException("Failed to unsign archive " + archive + ": " + e.getMessage(), e);
264 | }
265 | }
266 | }
267 |
268 | @Override
269 | protected void validateParameters() throws MojoExecutionException {
270 | super.validateParameters();
271 |
272 | if (maxTries < 1) {
273 | getLog().warn(getMessage("invalidMaxTries", maxTries));
274 | maxTries = 1;
275 | }
276 |
277 | if (maxRetryDelaySeconds < 0) {
278 | getLog().warn(getMessage("invalidMaxRetryDelaySeconds", maxRetryDelaySeconds));
279 | maxRetryDelaySeconds = 0;
280 | }
281 |
282 | if (threadCount < 1) {
283 | getLog().warn(getMessage("invalidThreadCount", threadCount));
284 | threadCount = 1;
285 | }
286 |
287 | if (tsa.length > 0 && tsacert.length > 0) {
288 | getLog().warn(getMessage("warnUsageTsaAndTsacertSimultaneous"));
289 | }
290 | if (tsapolicyid.length > tsa.length || tsapolicyid.length > tsacert.length) {
291 | getLog().warn(getMessage("warnUsageTsapolicyidTooMany", tsapolicyid.length, tsa.length, tsacert.length));
292 | }
293 | if (tsa.length > 1 && maxTries == 1) {
294 | getLog().warn(getMessage("warnUsageMultiTsaWithoutRetry", tsa.length));
295 | }
296 | if (tsacert.length > 1 && maxTries == 1) {
297 | getLog().warn(getMessage("warnUsageMultiTsacertWithoutRetry", tsacert.length));
298 | }
299 | tsaSelector = new TsaSelector(tsa, tsacert, tsapolicyid, tsadigestalg);
300 | }
301 |
302 | /**
303 | * {@inheritDoc}
304 | */
305 | @Override
306 | protected JarSignerRequest createRequest(File archive) throws MojoExecutionException {
307 | JarSignerSignRequest request = new JarSignerSignRequest();
308 | request.setSigfile(sigfile);
309 | updateJarSignerRequestWithTsa(request, tsaSelector.getServer());
310 | request.setCertchain(certchain);
311 |
312 | // Special handling for passwords through the Maven Security Dispatcher
313 | request.setKeypass(decrypt(keypass));
314 | return request;
315 | }
316 |
317 | /** Modifies JarSignerRequest with TSA parameters */
318 | private void updateJarSignerRequestWithTsa(JarSignerSignRequest request, TsaServer tsaServer) {
319 | request.setTsaLocation(tsaServer.getTsaUrl());
320 | request.setTsaAlias(tsaServer.getTsaAlias());
321 | request.setTsapolicyid(tsaServer.getTsaPolicyId());
322 | request.setTsadigestalg(tsaServer.getTsaDigestAlg());
323 | }
324 |
325 | /**
326 | * {@inheritDoc} Processing of files may be parallelized for increased performance.
327 | */
328 | @Override
329 | protected void processArchives(List archives) throws MojoExecutionException {
330 | ExecutorService executor = Executors.newFixedThreadPool(threadCount);
331 | List> futures = archives.stream()
332 | .map(file -> executor.submit((Callable) () -> {
333 | processArchive(file);
334 | return null; // Return dummy value to conform with Void type
335 | }))
336 | .collect(Collectors.toList());
337 | try {
338 | for (Future future : futures) {
339 | future.get(); // Wait for completion. Result ignored, but may raise any Exception
340 | }
341 | } catch (InterruptedException e) {
342 | Thread.currentThread().interrupt();
343 | throw new MojoExecutionException("Thread interrupted while waiting for jarsigner to complete", e);
344 | } catch (ExecutionException e) {
345 | if (e.getCause() instanceof MojoExecutionException) {
346 | throw (MojoExecutionException) e.getCause();
347 | }
348 | throw new MojoExecutionException("Error processing archives", e);
349 | } finally {
350 | // Shutdown of thread pool. If an Exception occurred, remaining threads will be aborted "best effort"
351 | executor.shutdownNow();
352 | }
353 | }
354 |
355 | /**
356 | * {@inheritDoc}
357 | *
358 | * Will retry signing up to maxTries times if it fails.
359 | *
360 | * @throws MojoExecutionException if all signing attempts fail
361 | */
362 | @Override
363 | protected void executeJarSigner(JarSigner jarSigner, JarSignerRequest request)
364 | throws JavaToolException, MojoExecutionException {
365 | for (int attempt = 0; attempt < maxTries; attempt++) {
366 | JavaToolResult result = jarSigner.execute(request);
367 | int resultCode = result.getExitCode();
368 | if (resultCode == 0) {
369 | return;
370 | }
371 | tsaSelector.registerFailure(); // Could be TSA server problem or something unrelated to TSA
372 |
373 | if (attempt < maxTries - 1) { // If not last attempt
374 | waitStrategy.waitAfterFailure(attempt, Duration.ofSeconds(maxRetryDelaySeconds));
375 | updateJarSignerRequestWithTsa((JarSignerSignRequest) request, tsaSelector.getServer());
376 | } else {
377 | // Last attempt failed, use this failure as resulting failure
378 | throw new MojoExecutionException(
379 | getMessage("failure", getCommandlineInfo(result.getCommandline()), resultCode));
380 | }
381 | }
382 | }
383 |
384 | /** Set current WaitStrategy. Package private for testing. */
385 | void setWaitStrategy(WaitStrategy waitStrategy) {
386 | this.waitStrategy = waitStrategy;
387 | }
388 |
389 | /** Wait/sleep after a signing failure before the next re-try should happen. */
390 | @FunctionalInterface
391 | interface WaitStrategy {
392 | /**
393 | * Will be called after a signing failure, if a re-try is about to happen. May as a side effect sleep current
394 | * thread for some time.
395 | *
396 | * @param attempt the attempt number (0 is the first)
397 | * @param maxRetryDelay the maximum duration to sleep (may be zero)
398 | * @throws MojoExecutionException if the sleep was interrupted
399 | */
400 | void waitAfterFailure(int attempt, Duration maxRetryDelay) throws MojoExecutionException;
401 | }
402 |
403 | private void defaultWaitStrategy(int attempt, Duration maxRetryDelay) throws MojoExecutionException {
404 | waitAfterFailure(attempt, maxRetryDelay, Thread::sleep);
405 | }
406 |
407 | /** Thread.sleep(long millis) interface to make testing easier */
408 | @FunctionalInterface
409 | interface Sleeper {
410 | void sleep(long millis) throws InterruptedException;
411 | }
412 |
413 | /** Package private for testing */
414 | void waitAfterFailure(int attempt, Duration maxRetryDelay, Sleeper sleeper) throws MojoExecutionException {
415 | // Use attempt as exponent in the exponential function, but limit it to avoid too big values.
416 | int exponentAttempt = Math.min(attempt, MAX_WAIT_EXPONENT_ATTEMPT);
417 | long delayMillis = (long) (Duration.ofSeconds(1).toMillis() * Math.pow(2, exponentAttempt));
418 | delayMillis = Math.min(delayMillis, maxRetryDelay.toMillis());
419 | if (delayMillis > 0) {
420 | getLog().info("Sleeping after failed attempt for " + (delayMillis / 1000) + " seconds...");
421 | try {
422 | sleeper.sleep(delayMillis);
423 | } catch (InterruptedException e) {
424 | Thread.currentThread().interrupt();
425 | throw new MojoExecutionException("Thread interrupted while waiting after failure", e);
426 | }
427 | }
428 | }
429 | }
430 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/maven/plugins/jarsigner/JarsignerVerifyMojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import javax.inject.Inject;
22 | import javax.inject.Named;
23 |
24 | import java.io.File;
25 | import java.io.IOException;
26 |
27 | import org.apache.maven.plugin.MojoExecutionException;
28 | import org.apache.maven.plugins.annotations.LifecyclePhase;
29 | import org.apache.maven.plugins.annotations.Mojo;
30 | import org.apache.maven.plugins.annotations.Parameter;
31 | import org.apache.maven.shared.jarsigner.JarSigner;
32 | import org.apache.maven.shared.jarsigner.JarSignerRequest;
33 | import org.apache.maven.shared.jarsigner.JarSignerUtil;
34 | import org.apache.maven.shared.jarsigner.JarSignerVerifyRequest;
35 | import org.apache.maven.shared.utils.cli.javatool.JavaToolException;
36 | import org.apache.maven.shared.utils.cli.javatool.JavaToolResult;
37 | import org.apache.maven.toolchain.ToolchainManager;
38 | import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
39 |
40 | /**
41 | * Checks the signatures of a project artifact and attachments using jarsigner.
42 | *
43 | * @author Christian Schulte
44 | * @since 1.0
45 | */
46 | @Mojo(name = "verify", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true)
47 | public class JarsignerVerifyMojo extends AbstractJarsignerMojo {
48 |
49 | /**
50 | * See options.
51 | */
52 | @Parameter(property = "jarsigner.certs", defaultValue = "false")
53 | private boolean certs;
54 |
55 | /**
56 | * When true
this will make the execute() operation fail,
57 | * throwing an exception, when verifying an unsigned jar.
58 | * Primarily to keep backwards compatibility with existing code, and allow reusing the
59 | * mojo in unattended operations when set to false
.
60 | *
61 | * @since 1.3
62 | **/
63 | @Parameter(property = "jarsigner.errorWhenNotSigned", defaultValue = "false")
64 | private boolean errorWhenNotSigned;
65 |
66 | @Inject
67 | public JarsignerVerifyMojo(
68 | JarSigner jarSigner,
69 | ToolchainManager toolchainManager,
70 | @Named("mng-4384") SecDispatcher securityDispatcher) {
71 | super(jarSigner, toolchainManager, securityDispatcher);
72 | }
73 |
74 | // for testing; invoked via reflection
75 | JarsignerVerifyMojo() {
76 | super(null, null, null);
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | protected JarSignerRequest createRequest(File archive) {
84 | JarSignerVerifyRequest request = new JarSignerVerifyRequest();
85 | request.setCerts(certs);
86 | return request;
87 | }
88 |
89 | @Override
90 | protected void preProcessArchive(File archive) throws MojoExecutionException {
91 | super.preProcessArchive(archive);
92 |
93 | if (errorWhenNotSigned) {
94 |
95 | // check archive if signed
96 | boolean archiveSigned;
97 | try {
98 | archiveSigned = JarSignerUtil.isArchiveSigned(archive);
99 | } catch (IOException e) {
100 | throw new MojoExecutionException(
101 | "Failed to check if archive " + archive + " is signed: " + e.getMessage(), e);
102 | }
103 |
104 | if (!archiveSigned) {
105 |
106 | // fails, archive must be signed
107 | throw new MojoExecutionException(getMessage("archiveNotSigned", archive));
108 | }
109 | }
110 | }
111 |
112 | @Override
113 | protected void executeJarSigner(JarSigner jarSigner, JarSignerRequest request)
114 | throws JavaToolException, MojoExecutionException {
115 | JavaToolResult result = jarSigner.execute(request);
116 | int resultCode = result.getExitCode();
117 | if (resultCode != 0) {
118 | throw new MojoExecutionException(
119 | getMessage("failure", getCommandlineInfo(result.getCommandline()), resultCode));
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/org/apache/maven/plugins/jarsigner/TsaSelector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.util.ArrayList;
22 | import java.util.Collections;
23 | import java.util.List;
24 | import java.util.concurrent.atomic.AtomicInteger;
25 |
26 | /**
27 | * Helper class to select a Time Stamping Authority (TSA) server along with parameters to send. The protocol is defined
28 | * in RFC 3161: Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP).
29 | *
30 | * From a jarsigner perspective there are two things that are important:
31 | * 1. Finding a TSA server URL
32 | * 2. What parameters to use for TSA server communication.
33 | *
34 | * Finding a URL can be done in two ways:
35 | * a) The end-user has specified an explicit URL (the most common way)
36 | * b) The end-user has specified a keystore alias that points to a certificate in the active keystore. From the
37 | * certificate the X509v3 extension "Subject Information Access" field is examined to find the TSA server URL.
38 | * Example:
39 | *
40 | * [vagrant@podmanhost ~]$ openssl x509 -noout -ext subjectInfoAccess -in tsa-server.crt
41 | * Subject Information Access:
42 | * AD Time Stamping - URI:http://timestamp.globalsign.com/tsa/r6advanced1
43 | *
44 | *
45 | * Each TSA server vendor typically has defined its own OID for what "policy" to use in the timestamping process. For
46 | * example GlobalSign might use 1.3.6.1.4.1.4146.2.3.1.2. A DigiCert TSA server would not accept this OID. In most cases
47 | * there is no need for the end-user to specify this because the TSA server will choose a default.
48 | *
49 | * jarsigner will send a message digest to the TSA server along with the message digest algorithm. For example
50 | * {@code SHA-384}. A TSA server might reject the chosen algorithm, but typically most TSA servers supports the "common"
51 | * ones (like SHA-256, SHA-384 and SHA-512). In most cases there is no need for the end-user to specify this because the
52 | * jarsigner tool choose a good default.
53 | */
54 | class TsaSelector {
55 |
56 | /** The current TsaServer in use (if any). One per thread */
57 | private final ThreadLocal currentTsaServer = new ThreadLocal<>();
58 |
59 | /** List of TSA servers. Will at minimum contain a dummy/empty value */
60 | private final List tsaServers;
61 |
62 | TsaSelector(String[] tsa, String[] tsacert, String[] tsapolicyid, String tsadigestalg) {
63 | List tsaServersTmp = new ArrayList<>();
64 |
65 | for (int i = 0; i < Math.max(tsa.length, tsacert.length); i++) {
66 | String tsaUrl = i < tsa.length ? tsa[i] : null;
67 | String tsaAlias = i < tsacert.length ? tsacert[i] : null;
68 | String tsaPolicyId = i < tsapolicyid.length ? tsapolicyid[i] : null;
69 | tsaServersTmp.add(new TsaServer(tsaUrl, tsaAlias, tsaPolicyId, tsadigestalg));
70 | }
71 |
72 | if (tsaServersTmp.isEmpty()) {
73 | tsaServersTmp.add(TsaServer.EMPTY);
74 | }
75 | this.tsaServers = Collections.unmodifiableList(tsaServersTmp);
76 | }
77 |
78 | /**
79 | * Gets the next "best" TSA server to use.
80 | *
81 | * Uses a "best effort" approach without any synchronization. It may not select the "snapshot-consistent" best TSA
82 | * server, but good enough.
83 | */
84 | TsaServer getServer() {
85 | TsaServer best = tsaServers.get(0);
86 | for (int i = 1; i < tsaServers.size(); i++) {
87 | if (best.failureCount.get() > tsaServers.get(i).failureCount.get()) {
88 | best = tsaServers.get(i);
89 | }
90 | }
91 | currentTsaServer.set(best);
92 | return best;
93 | }
94 |
95 | /**
96 | * Register that the current used TsaServer was involved in a jarsigner execution that failed. This could be a
97 | * problem with the TsaServer, but it could also be other factors unrelated to the TsaServer. Regardless of the
98 | * cause of the failure it is registered as a failure for the current used TsaServer to be used when determining the
99 | * next TsaServer to try.
100 | */
101 | void registerFailure() {
102 | if (currentTsaServer.get() != null) {
103 | currentTsaServer.get().failureCount.incrementAndGet();
104 | }
105 | }
106 |
107 | /** Representation of a single TSA server and the parameters to use for it */
108 | static class TsaServer {
109 | private static final TsaServer EMPTY = new TsaServer(null, null, null, null);
110 |
111 | private final AtomicInteger failureCount = new AtomicInteger(0);
112 | private final String tsaUrl;
113 | private final String tsaAlias;
114 | private final String tsaPolicyId;
115 | private final String tsaDigestAlg;
116 |
117 | private TsaServer(String tsaUrl, String tsaAlias, String tsaPolicyId, String tsaDigestAlg) {
118 | this.tsaUrl = tsaUrl;
119 | this.tsaAlias = tsaAlias;
120 | this.tsaPolicyId = tsaPolicyId;
121 | this.tsaDigestAlg = tsaDigestAlg;
122 | }
123 |
124 | String getTsaUrl() {
125 | return tsaUrl;
126 | }
127 |
128 | String getTsaAlias() {
129 | return tsaAlias;
130 | }
131 |
132 | String getTsaPolicyId() {
133 | return tsaPolicyId;
134 | }
135 |
136 | String getTsaDigestAlg() {
137 | return tsaDigestAlg;
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plexus/components.xml:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 | org.sonatype.plexus.components.sec.dispatcher.SecDispatcher
23 | mng-4384
24 | org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher
25 |
26 |
27 | org.sonatype.plexus.components.cipher.PlexusCipher
28 | mng-4384
29 | _cipher
30 |
31 |
32 |
33 | <_configuration-file>~/.m2/settings-security.xml
34 |
35 |
36 |
37 | org.sonatype.plexus.components.cipher.PlexusCipher
38 | mng-4384
39 | org.sonatype.plexus.components.cipher.DefaultPlexusCipher
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/main/resources/jarsigner.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 |
18 | disabled = Disabled
19 | ignoringAttachments = Forcibly ignoring attached artifacts
20 | unsupported = Unsupported artifact {0} ignored
21 | processing = Processing {0}
22 | processed = {0} archive(s) processed
23 | command = ''{0}''
24 | commandLineException = Failed executing ''{0}''
25 | failure = Failed executing ''{0}'' - exitcode {1,number}
26 | archiveNotSigned = Archive ''{0}'' is not signed
27 | invalidMaxTries = Invalid maxTries value. Was ''{0}'' but should be >= 1
28 | invalidMaxRetryDelaySeconds = Invalid maxRetryDelaySeconds value. Was ''{0}'' but should be >= 0
29 | invalidThreadCount = Invalid threadCount value. Was ''{0}'' but should be >= 1
30 | warnUsageTsaAndTsacertSimultaneous = Usage of both -tsa and -tsacert is undefined
31 | warnUsageTsapolicyidTooMany = Too many ({0}) number of OIDs given, but only {1} and {2} TSA URL and TSA certificate alias, respectively
32 | warnUsageMultiTsaWithoutRetry = {0} TSA URLs specified. Only first will be used because maxTries is set to 1
33 | warnUsageMultiTsacertWithoutRetry = {0} TSA certificate aliases specified. Only first will be used because maxTries is set to 1
34 |
--------------------------------------------------------------------------------
/src/main/resources/jarsigner_de.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 |
18 | disabled = Deaktiviert
19 | ignoringAttachments = Verarbeitung von angeh\u00E4ngten Artefakten unterdr\u00FCckt
20 | unsupported = Nicht unterst\u00FCtztes Artefakt {0} ignoriert
21 | processing = Verarbeite {0}
22 | processed = {0} Archiv(e) verarbeitet
23 | command = ''{0}''
24 | commandLineException = Ausf\u00FChrung von ''{0}'' gescheitert
25 | failure = Ausf\u00FChrung von ''{0}'' fehlgeschlagen - Ergebniscode ({1,number})
26 | archiveNotSigned = Archive ''{0}'' nicht unterdr\u00FCckt
--------------------------------------------------------------------------------
/src/main/resources/jarsigner_en.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 |
18 | # NOTE:
19 | # This bundle is intentionally empty because English strings are provided by the base bundle via the parent chain. It
20 | # must be provided nevertheless such that a request for locale "en" will not erroneously pick up the bundle for the
21 | # JVM's default locale (which need not be "en"). See the method javadoc about
22 | # ResourceBundle.getBundle(String, Locale, ClassLoader)
23 | # for a full description of the lookup strategy.
24 |
--------------------------------------------------------------------------------
/src/main/resources/jarsigner_fr.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 |
18 | ignoringAttachments=Ignorer les fichiers attach\u00E9s
19 | disabled=D\u00E9sactiv\u00E9
20 | unsupported=Artifact non support\u00E9 {0} ignor\u00E9
21 | processing=En cours de traitement {0}
22 | processed={0} archive(s) trait\u00E9es
23 | command=''{0}''
24 | commandLineException=Erreur lors de l'ex\u00E9cution ''{0}''
25 | failure=Erreur lors de l'ex\u00E9cution ''{0}'' - code de sortie {1,number}
26 | archiveNotSigned = L'archive ''{0}'' n'est pas signée
--------------------------------------------------------------------------------
/src/site/apt/examples/sign-and-verify-project.apt.vm:
--------------------------------------------------------------------------------
1 | ------
2 | Sign and verify a project
3 | ------
4 | Christian Schulte
5 | ------
6 | 08 April 2009
7 | ------
8 |
9 | ~~ Licensed to the Apache Software Foundation (ASF) under one
10 | ~~ or more contributor license agreements. See the NOTICE file
11 | ~~ distributed with this work for additional information
12 | ~~ regarding copyright ownership. The ASF licenses this file
13 | ~~ to you under the Apache License, Version 2.0 (the
14 | ~~ "License"); you may not use this file except in compliance
15 | ~~ with the License. You may obtain a copy of the License at
16 | ~~
17 | ~~ http://www.apache.org/licenses/LICENSE-2.0
18 | ~~
19 | ~~ Unless required by applicable law or agreed to in writing,
20 | ~~ software distributed under the License is distributed on an
21 | ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22 | ~~ KIND, either express or implied. See the License for the
23 | ~~ specific language governing permissions and limitations
24 | ~~ under the License.
25 |
26 |
27 | Sign and verify a project
28 |
29 | If you need to sign a project artifact and all attached artifacts and want
30 | to verify the signatures afterwards, just configure the sign and verify goal
31 | appropriately in your <<>> for the signing to occur automatically
32 | during the package phase and for the verification to occur during the verify
33 | phase.
34 |
35 | +-----------------+
36 |
37 | ...
38 |
39 |
40 | ...
41 |
42 | org.apache.maven.plugins
43 | maven-jarsigner-plugin
44 | ${project.version}
45 |
46 |
47 | sign
48 |
49 | sign
50 |
51 |
52 |
53 | verify
54 |
55 | verify
56 |
57 |
58 |
59 |
60 | ...
61 |
62 |
63 | ...
64 |
65 | +-----------------+
66 |
67 | Note: The sign goal requires at least the alias to use for signing. This alias
68 | can be passed using the command line like <<<-Djarsigner.alias="Alias Name">>>
69 | or set as a property in the <<>> file when not configured in the POM.
70 |
--------------------------------------------------------------------------------
/src/site/apt/index.apt.vm:
--------------------------------------------------------------------------------
1 | ------
2 | Introduction
3 | ------
4 | Christian Schulte
5 | ------
6 | 2013-07-22
7 | ------
8 |
9 | ~~ Licensed to the Apache Software Foundation (ASF) under one
10 | ~~ or more contributor license agreements. See the NOTICE file
11 | ~~ distributed with this work for additional information
12 | ~~ regarding copyright ownership. The ASF licenses this file
13 | ~~ to you under the Apache License, Version 2.0 (the
14 | ~~ "License"); you may not use this file except in compliance
15 | ~~ with the License. You may obtain a copy of the License at
16 | ~~
17 | ~~ http://www.apache.org/licenses/LICENSE-2.0
18 | ~~
19 | ~~ Unless required by applicable law or agreed to in writing,
20 | ~~ software distributed under the License is distributed on an
21 | ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22 | ~~ KIND, either express or implied. See the License for the
23 | ~~ specific language governing permissions and limitations
24 | ~~ under the License.
25 |
26 | ~~ NOTE: For help with the syntax of this file, see:
27 | ~~ http://maven.apache.org/doxia/references/apt-format.html
28 |
29 | ${project.name}
30 |
31 | This plugin provides the capability to sign or verify a project artifact
32 | and attachments using jarsigner.
33 |
34 | * Goals Overview
35 |
36 | * {{{./sign-mojo.html}jarsigner:sign}} sign a project artifact and attached artifacts.
37 |
38 | * {{{./verify-mojo.html}jarsigner:verify}} verify a project artifact and attached artifacts.
39 |
40 | []
41 |
42 | * Usage
43 |
44 | General instructions on how to use the Jarsigner Plugin can be found on the {{{./usage.html}usage page}}. Some more
45 | specific use cases are described in the examples given below. Additionally, users can contribute to the
46 | {{{https://github.com/apache/maven-jarsigner-plugin}GitHub project}}.
47 |
48 | In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel
49 | free to contact the {{{./mailing-lists.html}user mailing list}}. The posts to the mailing list are archived and could
50 | already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching
51 | the {{{./mailing-lists.html}mail archive}}.
52 |
53 | If you feel like the plugin is missing a feature or has a defect, you can file a feature request or bug report in our
54 | {{{./issue-management.html}issue tracker}}. When creating a new issue, please provide a comprehensive description of your
55 | concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason,
56 | entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated.
57 | Of course, patches are welcome, too. Contributors can check out the project from our
58 | {{{./scm.html}source repository}} and will find supplementary information in the
59 | {{{https://maven.apache.org/guides/development/guide-helping.html}guide to helping with Maven}}.
60 |
61 | * Examples
62 |
63 | To provide you with better understanding of some usages of the Jarsigner
64 | Plugin, you can take a look at the following example:
65 |
66 | * {{{./examples/sign-and-verify-project.html}Sign and verify a project}}
67 |
68 | []
69 |
--------------------------------------------------------------------------------
/src/site/apt/usage.apt.vm:
--------------------------------------------------------------------------------
1 | ------
2 | Usage
3 | ------
4 | Christian Schulte
5 | ------
6 | 08 April 2009
7 | ------
8 |
9 | ~~ Licensed to the Apache Software Foundation (ASF) under one
10 | ~~ or more contributor license agreements. See the NOTICE file
11 | ~~ distributed with this work for additional information
12 | ~~ regarding copyright ownership. The ASF licenses this file
13 | ~~ to you under the Apache License, Version 2.0 (the
14 | ~~ "License"); you may not use this file except in compliance
15 | ~~ with the License. You may obtain a copy of the License at
16 | ~~
17 | ~~ http://www.apache.org/licenses/LICENSE-2.0
18 | ~~
19 | ~~ Unless required by applicable law or agreed to in writing,
20 | ~~ software distributed under the License is distributed on an
21 | ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22 | ~~ KIND, either express or implied. See the License for the
23 | ~~ specific language governing permissions and limitations
24 | ~~ under the License.
25 |
26 | ~~ NOTE: For help with the syntax of this file, see:
27 | ~~ http://maven.apache.org/doxia/references/apt-format.html
28 |
29 | Usage
30 |
31 | Some brief examples on how to use this plugin.
32 |
33 | * Signing a project artifact and attachments
34 |
35 | If you need to sign a project artifact and all attached artifacts, just
36 | configure the sign goal appropriately in your <<>> for the
37 | signing to occur automatically during the package phase.
38 |
39 | +-----------------+
40 |
41 | ...
42 |
43 |
44 | ...
45 |
46 | org.apache.maven.plugins
47 | maven-jarsigner-plugin
48 | ${project.version}
49 |
50 |
51 | sign
52 |
53 | sign
54 |
55 |
56 |
57 |
58 | /path/to/the/keystore
59 | Alias name
60 | Store password
61 | Key password
62 |
63 |
64 | ...
65 |
66 |
67 | ...
68 |
69 | +-----------------+
70 |
71 | <> you can encrypt <<>> and <<>> using the
72 | maven encryption mechanism.
73 |
74 | See {{{https://maven.apache.org/guides/mini/guide-encryption.html}Maven encryption guide}}.
75 |
76 | * Verifying the signature of a project artifact and attachments
77 |
78 | If you need to verify the signatures of a project artifact and all attached
79 | artifacts, just configure the verify goal appropriately in your <<>>
80 | for the verification to occur automatically during the verify phase.
81 |
82 | +-----------------+
83 |
84 | ...
85 |
86 |
87 | ...
88 |
89 | org.apache.maven.plugins
90 | maven-jarsigner-plugin
91 | ${project.version}
92 |
93 |
94 | verify
95 |
96 | verify
97 |
98 |
99 |
100 |
101 | true
102 | true
103 |
104 |
105 | ...
106 |
107 |
108 | ...
109 |
110 | +-----------------+
111 |
112 | * How to disable attachment processing
113 |
114 | +-----------------+
115 | mvn ... -Djarsigner.attachments=false
116 | +-----------------+
117 |
118 |
119 | * How to disable the Jarsigner Plugin
120 |
121 | +-----------------+
122 | mvn ... -Djarsigner.skip=true
123 | +-----------------+
124 |
125 | For full documentation, please see the respective {{{./plugin-info.html}goal documentation}}.
126 |
127 | * How to use encrypted password
128 |
129 | Since version 1.3, you can pass to the plugin some password encrypted by the maven encryption mechanism.
130 |
--------------------------------------------------------------------------------
/src/site/fml/faq.fml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
27 |
28 |
29 | What is Jarsigner?
30 |
31 |
32 | You can read more about this tool in the offical guide:
33 | jarsigner - JAR Signing and Verification Tool.
34 |
35 |
36 |
37 |
38 | Is it possible to sign a single archive file?
39 |
40 |
41 | Signing or verifying a Java archive which is neither a project artifact
42 | nor an attached artifact can be done by using the archive
parameter
43 | of the sign
and verify
goals. If
44 | this parameter is set, the goals will process the specified archive and will not process any project
45 | artifacts.
46 |
47 |
48 |
49 |
50 | How can I unsign JARs before re-signing them with my key?
51 |
52 |
53 | To remove any existing signatures from the JARs before signing with your own key, simply set the parameter
54 | removeExistingSignatures
of the
55 | sign
mojo to true
. The resulting JAR will then appear
56 | to be signed exactly once.
57 |
58 |
59 |
60 |
61 | Why if I want to sign an artifact and then assembly there is some problem under windows?
62 |
63 |
64 | To fix the problem, just move the assembly execution so it comes after the jarsigner execution in the pom.
65 |
66 |
67 | The whole story of the problem can be found in MJARSIGNER-13 issue.
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/site/resources/download.cgi:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | #
20 | # Just call the standard mirrors.cgi script. It will use download.html
21 | # as the input template.
22 | exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $*
--------------------------------------------------------------------------------
/src/site/site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
25 |
26 |
35 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/site/xdoc/download.xml.vm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
24 | Download ${project.name} Source
25 |
26 |
27 |
28 |
29 |
30 | ${project.name} ${project.version} is distributed in source format.
31 |
32 | Use a source archive if you intend to build ${project.name} yourself.
33 |
34 | Otherwise, simply use the ready-made binary artifacts from central repository.
35 |
36 | ${project.name} is distributed under the Apache License, version 2.0.
37 |
38 |
39 |
40 | This is the current stable version of ${project.name}.
41 |
42 |
60 |
61 | It is essential that you verify the integrity of the downloaded file
62 | using the checksum (.sha512 file)
63 | or using the signature (.asc file) against the public KEYS used by the Apache Maven developers.
64 |
65 |
66 |
67 |
68 |
69 | It is strongly recommended to use the latest release version of ${project.name} to take advantage of the newest features and bug fixes.
70 | Older non-recommended releases can be found on our archive site.
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/JarsignerSignMojoParallelTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.time.Duration;
24 | import java.util.LinkedHashMap;
25 | import java.util.Map;
26 | import java.util.concurrent.ExecutorService;
27 | import java.util.concurrent.Executors;
28 | import java.util.concurrent.Future;
29 | import java.util.concurrent.Semaphore;
30 | import java.util.concurrent.ThreadFactory;
31 | import java.util.concurrent.TimeUnit;
32 |
33 | import org.apache.maven.artifact.Artifact;
34 | import org.apache.maven.plugin.MojoExecutionException;
35 | import org.apache.maven.plugin.logging.Log;
36 | import org.apache.maven.project.MavenProject;
37 | import org.apache.maven.shared.jarsigner.JarSigner;
38 | import org.apache.maven.shared.jarsigner.JarSignerSignRequest;
39 | import org.junit.After;
40 | import org.junit.Before;
41 | import org.junit.Rule;
42 | import org.junit.Test;
43 | import org.junit.rules.TemporaryFolder;
44 |
45 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_ERROR;
46 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_OK;
47 | import static org.hamcrest.CoreMatchers.containsString;
48 | import static org.hamcrest.MatcherAssert.assertThat;
49 | import static org.junit.Assert.*;
50 | import static org.mockito.ArgumentMatchers.any;
51 | import static org.mockito.ArgumentMatchers.contains;
52 | import static org.mockito.ArgumentMatchers.isA;
53 | import static org.mockito.Mockito.*;
54 |
55 | public class JarsignerSignMojoParallelTest {
56 | @Rule
57 | public TemporaryFolder folder = new TemporaryFolder();
58 |
59 | private MavenProject project = mock(MavenProject.class);
60 | private JarSigner jarSigner = mock(JarSigner.class);
61 | private File projectDir;
62 | private Map configuration = new LinkedHashMap<>();
63 | private MojoTestCreator mojoTestCreator;
64 | private ExecutorService executor;
65 | private Log log;
66 |
67 | @Before
68 | public void setUp() throws Exception {
69 | projectDir = folder.newFolder("dummy-project");
70 | configuration.put("processMainArtifact", "false");
71 | mojoTestCreator =
72 | new MojoTestCreator(JarsignerSignMojo.class, project, projectDir, jarSigner);
73 | log = mock(Log.class);
74 | mojoTestCreator.setLog(log);
75 | executor =
76 | Executors.newSingleThreadExecutor(namedThreadFactory(getClass().getSimpleName()));
77 | }
78 |
79 | @After
80 | public void tearDown() {
81 | executor.shutdown();
82 | }
83 |
84 | @Test(timeout = 30000)
85 | public void test10Files2Parallel() throws Exception {
86 | configuration.put("archiveDirectory", createArchives(10).getPath());
87 | configuration.put("threadCount", "2");
88 |
89 | // Make one jar file wait until some external event happens and let nine pass
90 | Semaphore semaphore = new Semaphore(9);
91 | when(jarSigner.execute(isA(JarSignerSignRequest.class))).then(invocation -> {
92 | semaphore.acquire();
93 | return RESULT_OK;
94 | });
95 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
96 |
97 | Future future = executor.submit(() -> {
98 | mojo.execute();
99 | return null;
100 | });
101 |
102 | // Wait until 10 invocation of execute() has happened (nine files are done and one are hanging)
103 | verify(jarSigner, timeout(Duration.ofSeconds(10).toMillis()).times(10)).execute(any());
104 | // Even though 10 invocations of execute() have happened, mojo is not yet done executing (it is waiting for one)
105 | assertFalse(future.isDone());
106 |
107 | semaphore.release(); // Release the one waiting jar file
108 | future.get(10, TimeUnit.SECONDS); // Wait for entire Mojo to finish
109 | assertTrue(future.isDone());
110 | }
111 |
112 | @Test(timeout = 30000)
113 | public void test10Files2Parallel3Hanging() throws Exception {
114 | configuration.put("archiveDirectory", createArchives(10).getPath());
115 | configuration.put("threadCount", "2");
116 |
117 | // Make three jar files wait until some external event happens and let seven pass
118 | Semaphore semaphore = new Semaphore(7);
119 | when(jarSigner.execute(isA(JarSignerSignRequest.class))).then(invocation -> {
120 | semaphore.acquire();
121 | return RESULT_OK;
122 | });
123 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
124 |
125 | Future future = executor.submit(() -> {
126 | mojo.execute();
127 | return null;
128 | });
129 |
130 | // Wait until 9 invocations to execute has happened (2 is ongoing and 1 has not yet happened)
131 | verify(jarSigner, timeout(Duration.ofSeconds(10).toMillis()).times(9)).execute(any());
132 | assertFalse(future.isDone());
133 |
134 | semaphore.release(); // Release one waiting jar file
135 |
136 | // Wait until 10 invocation to execute has happened (8 are done and 2 are hanging)
137 | verify(jarSigner, timeout(Duration.ofSeconds(10).toMillis()).times(10)).execute(any());
138 |
139 | semaphore.release(2); // Release last two jar files
140 | future.get(10, TimeUnit.SECONDS); // Wait for entire Mojo to finish
141 | assertTrue(future.isDone());
142 | }
143 |
144 | @Test(timeout = 30000)
145 | public void test10Files1Parallel() throws Exception {
146 | configuration.put("archiveDirectory", createArchives(10).getPath());
147 | configuration.put("threadCount", "1");
148 |
149 | // Make one jar file wait until some external event happens and let nine pass
150 | Semaphore semaphore = new Semaphore(9);
151 | when(jarSigner.execute(isA(JarSignerSignRequest.class))).then(invocation -> {
152 | semaphore.acquire();
153 | return RESULT_OK;
154 | });
155 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
156 |
157 | Future future = executor.submit(() -> {
158 | mojo.execute();
159 | return null;
160 | });
161 |
162 | // Wait until 10 invocation to execute has happened (nine has finished and one is hanging).
163 | verify(jarSigner, timeout(Duration.ofSeconds(10).toMillis()).times(10)).execute(any());
164 | assertFalse(future.isDone());
165 |
166 | semaphore.release(); // Release the one waiting jar file
167 | future.get(10, TimeUnit.SECONDS); // Wait for entire Mojo to finish
168 | assertTrue(future.isDone());
169 | }
170 |
171 | @Test(timeout = 30000)
172 | public void test10Files2ParallelOneFail() throws Exception {
173 | configuration.put("archiveDirectory", createArchives(10).getPath());
174 | configuration.put("threadCount", "2");
175 |
176 | when(jarSigner.execute(isA(JarSignerSignRequest.class)))
177 | .thenReturn(RESULT_OK)
178 | .thenReturn(RESULT_OK)
179 | .thenReturn(RESULT_ERROR)
180 | .thenReturn(RESULT_OK);
181 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
182 |
183 | MojoExecutionException mojoException = assertThrows(MojoExecutionException.class, () -> {
184 | mojo.execute();
185 | });
186 |
187 | assertThat(mojoException.getMessage(), containsString(String.valueOf("Failed executing 'jarsigner ")));
188 | }
189 |
190 | @Test
191 | public void testInvalidThreadCount() throws Exception {
192 | Artifact mainArtifact = TestArtifacts.createJarArtifact(projectDir, "my-project.jar");
193 | when(project.getArtifact()).thenReturn(mainArtifact);
194 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
195 | configuration.put("processMainArtifact", "true");
196 | configuration.put("threadCount", "0"); // Setting an "invalid" value
197 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
198 |
199 | mojo.execute();
200 |
201 | verify(jarSigner, times(1)).execute(any());
202 | verify(log).warn(contains("Invalid threadCount value"));
203 | verify(log).warn(contains("Was '0'"));
204 | }
205 |
206 | private File createArchives(int numberOfArchives) throws IOException {
207 | File archiveDirectory = new File(projectDir, "my_archive_dir");
208 | archiveDirectory.mkdir();
209 | for (int i = 0; i < numberOfArchives; i++) {
210 | TestArtifacts.createDummyZipFile(new File(archiveDirectory, "archive" + i + ".jar"));
211 | }
212 | return archiveDirectory;
213 | }
214 |
215 | private static ThreadFactory namedThreadFactory(String threadNamePrefix) {
216 | return r -> new Thread(r, threadNamePrefix + "-Thread");
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/JarsignerSignMojoRetryTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.time.Duration;
23 | import java.util.LinkedHashMap;
24 | import java.util.Locale;
25 | import java.util.Map;
26 | import java.util.concurrent.atomic.AtomicLong;
27 |
28 | import org.apache.maven.artifact.Artifact;
29 | import org.apache.maven.plugin.MojoExecutionException;
30 | import org.apache.maven.plugin.logging.Log;
31 | import org.apache.maven.plugins.jarsigner.JarsignerSignMojo.Sleeper;
32 | import org.apache.maven.plugins.jarsigner.JarsignerSignMojo.WaitStrategy;
33 | import org.apache.maven.project.MavenProject;
34 | import org.apache.maven.shared.jarsigner.JarSigner;
35 | import org.apache.maven.shared.jarsigner.JarSignerSignRequest;
36 | import org.apache.maven.shared.utils.cli.javatool.JavaToolResult;
37 | import org.junit.After;
38 | import org.junit.Before;
39 | import org.junit.Rule;
40 | import org.junit.Test;
41 | import org.junit.rules.TemporaryFolder;
42 |
43 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_ERROR;
44 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_OK;
45 | import static org.hamcrest.CoreMatchers.containsString;
46 | import static org.hamcrest.CoreMatchers.not;
47 | import static org.hamcrest.MatcherAssert.assertThat;
48 | import static org.junit.Assert.*;
49 | import static org.mockito.ArgumentMatchers.any;
50 | import static org.mockito.ArgumentMatchers.contains;
51 | import static org.mockito.Mockito.argThat;
52 | import static org.mockito.Mockito.mock;
53 | import static org.mockito.Mockito.times;
54 | import static org.mockito.Mockito.verify;
55 | import static org.mockito.Mockito.when;
56 |
57 | public class JarsignerSignMojoRetryTest {
58 | @Rule
59 | public TemporaryFolder folder = new TemporaryFolder();
60 |
61 | private Locale originalLocale;
62 | private MavenProject project = mock(MavenProject.class);
63 | private JarSigner jarSigner = mock(JarSigner.class);
64 | private WaitStrategy waitStrategy = mock(WaitStrategy.class);
65 | private File projectDir;
66 | private Map configuration = new LinkedHashMap<>();
67 | private Log log;
68 | private MojoTestCreator mojoTestCreator;
69 |
70 | @Before
71 | public void setUp() throws Exception {
72 | originalLocale = Locale.getDefault();
73 | Locale.setDefault(Locale.ENGLISH); // For English ResourceBundle to test log messages
74 | projectDir = folder.newFolder("dummy-project");
75 | mojoTestCreator =
76 | new MojoTestCreator(JarsignerSignMojo.class, project, projectDir, jarSigner);
77 | log = mock(Log.class);
78 | mojoTestCreator.setLog(log);
79 | Artifact mainArtifact = TestArtifacts.createJarArtifact(projectDir, "my-project.jar");
80 | when(project.getArtifact()).thenReturn(mainArtifact);
81 | }
82 |
83 | @After
84 | public void tearDown() {
85 | Locale.setDefault(originalLocale);
86 | }
87 |
88 | @Test
89 | public void testSignSuccessOnFirst() throws Exception {
90 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
91 | configuration.put("maxTries", "1");
92 | mojoTestCreator.setWaitStrategy(waitStrategy);
93 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
94 |
95 | mojo.execute();
96 |
97 | verify(jarSigner)
98 | .execute(argThat(request -> request.getArchive().getPath().endsWith("my-project.jar")));
99 | verify(waitStrategy, times(0)).waitAfterFailure(0, Duration.ofSeconds(0));
100 | }
101 |
102 | @Test
103 | public void testSignFailureOnFirst() throws Exception {
104 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_ERROR);
105 | configuration.put("maxTries", "1");
106 | mojoTestCreator.setWaitStrategy(waitStrategy);
107 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
108 | assertThrows(MojoExecutionException.class, () -> {
109 | mojo.execute();
110 | });
111 | verify(jarSigner, times(1)).execute(any());
112 | verify(waitStrategy, times(0)).waitAfterFailure(0, Duration.ofSeconds(0));
113 | }
114 |
115 | @Test
116 | public void testSignFailureOnFirstSuccessOnSecond() throws Exception {
117 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
118 | .thenReturn(RESULT_ERROR)
119 | .thenReturn(RESULT_OK);
120 | configuration.put("maxTries", "2");
121 | mojoTestCreator.setWaitStrategy(waitStrategy);
122 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
123 |
124 | mojo.execute();
125 |
126 | verify(jarSigner, times(2)).execute(any());
127 | verify(waitStrategy, times(1)).waitAfterFailure(0, Duration.ofSeconds(0));
128 | }
129 |
130 | @Test
131 | public void testSignFailureOnFirstFailureOnSecond() throws Exception {
132 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
133 | .thenReturn(RESULT_ERROR)
134 | .thenReturn(RESULT_ERROR);
135 | configuration.put("maxTries", "2");
136 | mojoTestCreator.setWaitStrategy(waitStrategy);
137 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
138 | assertThrows(MojoExecutionException.class, () -> {
139 | mojo.execute();
140 | });
141 | verify(jarSigner, times(2)).execute(any());
142 | verify(waitStrategy, times(1)).waitAfterFailure(0, Duration.ofSeconds(0));
143 | }
144 |
145 | @Test
146 | public void testInvalidMaxTries_zero() throws Exception {
147 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_ERROR);
148 |
149 | configuration.put("maxTries", "0"); // Setting an "invalid" value
150 | mojoTestCreator.setWaitStrategy(waitStrategy);
151 |
152 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
153 |
154 | assertThrows(MojoExecutionException.class, () -> {
155 | mojo.execute();
156 | });
157 |
158 | verify(jarSigner, times(1)).execute(any()); // Should have tried exactly one time, regardless of invalid value
159 | verify(log).warn(contains("Invalid maxTries"));
160 | verify(log).warn(contains("0"));
161 | }
162 |
163 | @Test
164 | public void testInvalidMaxTries_negative() throws Exception {
165 | // Make result ok, to make this test check more things (compared to testInvalidMaxTries_zero())
166 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
167 |
168 | configuration.put("maxTries", "-2"); // Setting an "invalid" value
169 | mojoTestCreator.setWaitStrategy(waitStrategy);
170 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
171 |
172 | mojo.execute();
173 |
174 | verify(jarSigner, times(1)).execute(any()); // Should have tried exactly one time, regardless of invalid value
175 | verify(log).warn(contains("Invalid maxTries"));
176 | verify(log).warn(contains("-2"));
177 | }
178 |
179 | @Test
180 | public void testMaxRetryDelaySeconds() throws Exception {
181 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
182 | .thenReturn(RESULT_ERROR)
183 | .thenReturn(RESULT_ERROR)
184 | .thenReturn(RESULT_OK);
185 |
186 | configuration.put("maxTries", "3");
187 | configuration.put("maxRetryDelaySeconds", "30");
188 | mojoTestCreator.setWaitStrategy(waitStrategy);
189 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
190 |
191 | mojo.execute();
192 |
193 | verify(waitStrategy, times(1)).waitAfterFailure(0, Duration.ofSeconds(30));
194 | verify(waitStrategy, times(1)).waitAfterFailure(1, Duration.ofSeconds(30));
195 | }
196 |
197 | @Test
198 | public void testInvalidMaxRetryDelaySeconds_negative() throws Exception {
199 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
200 | .thenReturn(RESULT_ERROR)
201 | .thenReturn(RESULT_OK);
202 |
203 | configuration.put("maxTries", "10");
204 | configuration.put("maxRetryDelaySeconds", "-5"); // Setting an "invalid" value
205 | mojoTestCreator.setWaitStrategy(waitStrategy);
206 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
207 |
208 | mojo.execute();
209 |
210 | verify(waitStrategy).waitAfterFailure(0, Duration.ofSeconds(0));
211 | verify(jarSigner, times(2)).execute(any());
212 | verify(log).warn(contains("Invalid maxRetryDelaySeconds"));
213 | verify(log).warn(contains("-5"));
214 | }
215 |
216 | @Test
217 | public void testDefaultWaitStrategy() throws Exception {
218 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
219 |
220 | long NO_SLEEP_VALUE = 42_001;
221 | // Storage of the most recent sleep value
222 | AtomicLong sleepValue = new AtomicLong(NO_SLEEP_VALUE);
223 | Sleeper sleeper = value -> sleepValue.set(value);
224 |
225 | mojo.waitAfterFailure(0, Duration.ofSeconds(0), sleeper);
226 | assertEquals(NO_SLEEP_VALUE, sleepValue.get());
227 |
228 | mojo.waitAfterFailure(1, Duration.ofSeconds(0), sleeper);
229 | assertEquals(NO_SLEEP_VALUE, sleepValue.get());
230 |
231 | mojo.waitAfterFailure(0, Duration.ofSeconds(1), sleeper);
232 | assertEquals(1000, sleepValue.get());
233 | verify(log).info(contains("for 1 seconds"));
234 |
235 | mojo.waitAfterFailure(1, Duration.ofSeconds(1), sleeper);
236 | assertEquals(1000, sleepValue.get());
237 | mojo.waitAfterFailure(2, Duration.ofSeconds(1), sleeper);
238 | assertEquals(1000, sleepValue.get());
239 |
240 | mojo.waitAfterFailure(3, Duration.ofSeconds(100), sleeper);
241 | assertEquals(8000, sleepValue.get());
242 |
243 | mojo.waitAfterFailure(Integer.MAX_VALUE, Duration.ofSeconds(100), sleeper);
244 | assertEquals(100_000, sleepValue.get());
245 |
246 | sleepValue.set(NO_SLEEP_VALUE); // "reset" sleep value
247 | mojo.waitAfterFailure(Integer.MIN_VALUE, Duration.ofSeconds(100), sleeper);
248 | // Make sure sleep has not been invoked, should be the "reset" value
249 | assertEquals(NO_SLEEP_VALUE, sleepValue.get());
250 |
251 | // Testing the attempt limit used in exponential function. Will return a odd value (2^20).
252 | mojo.waitAfterFailure(10000, Duration.ofDays(356), sleeper);
253 | assertEquals(Duration.ofSeconds(1048576).toMillis(), sleepValue.get());
254 | // Testing of attempt limit, when using a smaller maxRetryDelay
255 | mojo.waitAfterFailure(10000, Duration.ofDays(1), sleeper);
256 | assertEquals(Duration.ofDays(1).toMillis(), sleepValue.get());
257 |
258 | Sleeper iterruptedSleeper = value -> {
259 | throw new InterruptedException("Thread was interrupted while sleeping.");
260 | };
261 | MojoExecutionException mojoException = assertThrows(MojoExecutionException.class, () -> {
262 | mojo.waitAfterFailure(0, Duration.ofSeconds(10), iterruptedSleeper);
263 | });
264 | assertThat(mojoException.getMessage(), containsString("interrupted while waiting after failure"));
265 | }
266 |
267 | /** Check that the error returned from a re-try scenario where all execution fails is the "correct" error */
268 | @Test
269 | public void testLastErrorReturned() throws Exception {
270 | JavaToolResult lastError = new JavaToolResult();
271 | lastError.setExitCode(42); // The exit code of the last jarsigner execution
272 | lastError.setExecutionException(null);
273 | lastError.setCommandline(RESULT_ERROR.getCommandline());
274 |
275 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
276 | .thenReturn(RESULT_ERROR)
277 | .thenReturn(lastError);
278 |
279 | configuration.put("maxTries", "5");
280 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
281 |
282 | MojoExecutionException mojoException = assertThrows(MojoExecutionException.class, () -> {
283 | mojo.execute();
284 | });
285 |
286 | // Make sure that the last error exit code is present
287 | assertThat(mojoException.getMessage(), containsString(String.valueOf(42)));
288 | // Make sure that the first error exit code is not present
289 | assertThat(mojoException.getMessage(), not(containsString(String.valueOf(1))));
290 | }
291 | }
292 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/JarsignerSignMojoTsaTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.util.ArrayList;
24 | import java.util.LinkedHashMap;
25 | import java.util.List;
26 | import java.util.Locale;
27 | import java.util.Map;
28 |
29 | import org.apache.maven.artifact.Artifact;
30 | import org.apache.maven.plugin.logging.Log;
31 | import org.apache.maven.project.MavenProject;
32 | import org.apache.maven.shared.jarsigner.JarSigner;
33 | import org.apache.maven.shared.jarsigner.JarSignerSignRequest;
34 | import org.junit.After;
35 | import org.junit.Before;
36 | import org.junit.Rule;
37 | import org.junit.Test;
38 | import org.junit.rules.TemporaryFolder;
39 | import org.mockito.ArgumentCaptor;
40 |
41 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_ERROR;
42 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_OK;
43 | import static org.hamcrest.CoreMatchers.everyItem;
44 | import static org.hamcrest.MatcherAssert.assertThat;
45 | import static org.junit.Assert.*;
46 | import static org.mockito.ArgumentMatchers.any;
47 | import static org.mockito.ArgumentMatchers.contains;
48 | import static org.mockito.Mockito.mock;
49 | import static org.mockito.Mockito.times;
50 | import static org.mockito.Mockito.verify;
51 | import static org.mockito.Mockito.when;
52 |
53 | public class JarsignerSignMojoTsaTest {
54 | @Rule
55 | public TemporaryFolder folder = new TemporaryFolder();
56 |
57 | private Locale originalLocale;
58 | private MavenProject project = mock(MavenProject.class);
59 | private JarSigner jarSigner = mock(JarSigner.class);
60 |
61 | private File projectDir;
62 | private Map configuration = new LinkedHashMap<>();
63 | private Log log;
64 | private MojoTestCreator mojoTestCreator;
65 |
66 | @Before
67 | public void setUp() throws Exception {
68 | originalLocale = Locale.getDefault();
69 | Locale.setDefault(Locale.ENGLISH); // For English ResourceBundle to test log messages
70 | projectDir = folder.newFolder("dummy-project");
71 | mojoTestCreator =
72 | new MojoTestCreator(JarsignerSignMojo.class, project, projectDir, jarSigner);
73 | log = mock(Log.class);
74 | mojoTestCreator.setLog(log);
75 | Artifact mainArtifact = TestArtifacts.createJarArtifact(projectDir, "my-project.jar");
76 | when(project.getArtifact()).thenReturn(mainArtifact);
77 | }
78 |
79 | @After
80 | public void tearDown() {
81 | Locale.setDefault(originalLocale);
82 | }
83 |
84 | @Test
85 | public void testAllTsaParameters() throws Exception {
86 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
87 | configuration.put("archiveDirectory", createArchives(2).getPath());
88 | configuration.put("tsa", "http://my-timestamp.server.com");
89 | configuration.put("tsacert", "mytsacertalias"); // Normally you would not set both "tsacert alias" and "tsa url"
90 | configuration.put("tsapolicyid", "0.1.2.3.4");
91 | configuration.put("tsadigestalg", "SHA-384");
92 |
93 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
94 |
95 | mojo.execute();
96 |
97 | ArgumentCaptor requestArgument = ArgumentCaptor.forClass(JarSignerSignRequest.class);
98 | verify(jarSigner, times(3)).execute(requestArgument.capture());
99 | List requests = requestArgument.getAllValues();
100 | assertThat(requests, everyItem(RequestMatchers.hasTsa("http://my-timestamp.server.com")));
101 | assertThat(requests, everyItem(RequestMatchers.hasTsacert("mytsacertalias")));
102 | assertThat(requests, everyItem(RequestMatchers.hasTsaPolicyid("0.1.2.3.4")));
103 | assertThat(requests, everyItem(RequestMatchers.hasTsaDigestalg("SHA-384")));
104 | }
105 |
106 | @Test
107 | public void testMutipleTsa() throws Exception {
108 | // Special setup (non-normal) Mockito, because the same JarSignerSignRequest instance is used with modified URL
109 | List tsaUrls = new ArrayList<>();
110 | when(jarSigner.execute(any(JarSignerSignRequest.class)))
111 | .thenAnswer(invocation -> {
112 | JarSignerSignRequest request =
113 | (JarSignerSignRequest) invocation.getArguments()[0];
114 | tsaUrls.add(request.getTsaLocation());
115 | return RESULT_ERROR;
116 | })
117 | .thenAnswer(invocation -> {
118 | JarSignerSignRequest request =
119 | (JarSignerSignRequest) invocation.getArguments()[0];
120 | tsaUrls.add(request.getTsaLocation());
121 | return RESULT_OK;
122 | });
123 |
124 | configuration.put("maxTries", "10");
125 | configuration.put("tsa", "http://my-timestamp.server.com,http://other-timestamp.example.com");
126 |
127 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
128 |
129 | mojo.execute();
130 |
131 | verify(jarSigner, times(2)).execute(any());
132 | assertEquals("http://my-timestamp.server.com", tsaUrls.get(0));
133 | assertEquals("http://other-timestamp.example.com", tsaUrls.get(1));
134 | }
135 |
136 | @Test
137 | public void testVerifyUsageOfBothTsaAndTsacert() throws Exception {
138 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
139 | configuration.put("maxTries", "2");
140 | configuration.put("tsa", "http://my-timestamp.server.com");
141 | configuration.put("tsacert", "mytsacertalias");
142 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
143 |
144 | mojo.execute();
145 |
146 | verify(log).warn(contains("Usage of both -tsa and -tsacert is undefined"));
147 | }
148 |
149 | @Test
150 | public void testVerifyUsageOfDifferentNumberOfTsapolicyidAndTsa() throws Exception {
151 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
152 | configuration.put("maxTries", "2");
153 | configuration.put("tsa", "http://my-timestamp1.server.com,http://my-timestamp2.server.com");
154 | configuration.put("tsapolicyid", "1.1,1.2,1.3"); // Too many OIDs specified
155 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
156 |
157 | mojo.execute();
158 |
159 | verify(log).warn(contains("Too many (3) number of OIDs given"));
160 | }
161 |
162 | @Test
163 | public void testVerifyUsageOfDifferentNumberOfTsapolicyidAndTsacert() throws Exception {
164 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
165 | configuration.put("maxTries", "2");
166 | configuration.put("tsacert", "alias1,alias2");
167 | configuration.put("tsapolicyid", "1.1,1.2,1.3"); // Too many OIDs specified
168 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
169 |
170 | mojo.execute();
171 |
172 | // Alomst the same warning log as previous test case
173 | verify(log).warn(contains("Too many (3) number of OIDs given"));
174 | }
175 |
176 | @Test
177 | public void testVerifyMultipleTsaButNoRetry() throws Exception {
178 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
179 | configuration.put("tsa", "http://my-timestamp1.server.com,http://my-timestamp2.server.com");
180 | configuration.put("maxTries", "1");
181 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
182 |
183 | mojo.execute();
184 |
185 | verify(log).warn(contains("2 TSA URLs specified. Only first will be used because maxTries is set to 1"));
186 | }
187 |
188 | @Test
189 | public void testVerifyMultipleTsacertButNoRetry() throws Exception {
190 | when(jarSigner.execute(any(JarSignerSignRequest.class))).thenReturn(RESULT_OK);
191 | configuration.put("tsacert", "alias1,alias2");
192 | configuration.put("maxTries", "1");
193 | JarsignerSignMojo mojo = mojoTestCreator.configure(configuration);
194 |
195 | mojo.execute();
196 |
197 | verify(log).warn(contains("2 TSA certificate aliases specified. Only first"));
198 | }
199 |
200 | private File createArchives(int numberOfArchives) throws IOException {
201 | File archiveDirectory = new File(projectDir, "my_archive_dir");
202 | archiveDirectory.mkdir();
203 | for (int i = 0; i < numberOfArchives; i++) {
204 | TestArtifacts.createDummyZipFile(new File(archiveDirectory, "archive" + i + ".jar"));
205 | }
206 | return archiveDirectory;
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/JarsignerVerifyMojoTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.util.LinkedHashMap;
23 | import java.util.Map;
24 |
25 | import org.apache.maven.artifact.Artifact;
26 | import org.apache.maven.plugin.MojoExecutionException;
27 | import org.apache.maven.plugin.logging.Log;
28 | import org.apache.maven.project.MavenProject;
29 | import org.apache.maven.shared.jarsigner.JarSigner;
30 | import org.apache.maven.shared.jarsigner.JarSignerVerifyRequest;
31 | import org.junit.Before;
32 | import org.junit.Rule;
33 | import org.junit.Test;
34 | import org.junit.rules.TemporaryFolder;
35 | import org.mockito.ArgumentCaptor;
36 | import org.mockito.hamcrest.MockitoHamcrest;
37 |
38 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_ERROR;
39 | import static org.apache.maven.plugins.jarsigner.TestJavaToolResults.RESULT_OK;
40 | import static org.hamcrest.CoreMatchers.containsString;
41 | import static org.hamcrest.CoreMatchers.startsWith;
42 | import static org.hamcrest.MatcherAssert.assertThat;
43 | import static org.junit.Assert.*;
44 | import static org.mockito.ArgumentMatchers.any;
45 | import static org.mockito.ArgumentMatchers.argThat;
46 | import static org.mockito.Mockito.mock;
47 | import static org.mockito.Mockito.verify;
48 | import static org.mockito.Mockito.when;
49 |
50 | public class JarsignerVerifyMojoTest {
51 |
52 | @Rule
53 | public TemporaryFolder folder = new TemporaryFolder();
54 |
55 | private MavenProject project = mock(MavenProject.class);
56 | private JarSigner jarSigner = mock(JarSigner.class);
57 | private File dummyMavenProjectDir;
58 | private Map configuration = new LinkedHashMap<>();
59 | private Log log;
60 | private MojoTestCreator mojoTestCreator;
61 |
62 | @Before
63 | public void setUp() throws Exception {
64 | dummyMavenProjectDir = folder.newFolder("dummy-project");
65 | mojoTestCreator = new MojoTestCreator(
66 | JarsignerVerifyMojo.class, project, dummyMavenProjectDir, jarSigner);
67 | log = mock(Log.class);
68 | mojoTestCreator.setLog(log);
69 | }
70 |
71 | /** Standard Java project with nothing special configured */
72 | @Test
73 | public void testStandardJavaProject() throws Exception {
74 | Artifact mainArtifact = TestArtifacts.createJarArtifact(dummyMavenProjectDir, "my-project.jar");
75 | when(project.getArtifact()).thenReturn(mainArtifact);
76 | when(jarSigner.execute(any(JarSignerVerifyRequest.class))).thenReturn(RESULT_OK);
77 | JarsignerVerifyMojo mojo = mojoTestCreator.configure(configuration);
78 |
79 | mojo.execute();
80 |
81 | ArgumentCaptor requestArgument = ArgumentCaptor.forClass(JarSignerVerifyRequest.class);
82 | verify(jarSigner).execute(requestArgument.capture());
83 | JarSignerVerifyRequest request = requestArgument.getValue();
84 |
85 | assertFalse(request.isVerbose());
86 | assertNull(request.getKeystore());
87 | assertNull(request.getStoretype());
88 | assertNull(request.getStorepass());
89 | assertNull(request.getAlias());
90 | assertNull(request.getProviderName());
91 | assertNull(request.getProviderClass());
92 | assertNull(request.getProviderArg());
93 | assertNull(request.getMaxMemory());
94 | assertThat(request.getArguments()[0], startsWith("-J-Dfile.encoding="));
95 | assertEquals(dummyMavenProjectDir, request.getWorkingDirectory());
96 | assertEquals(mainArtifact.getFile(), request.getArchive());
97 | assertFalse(request.isProtectedAuthenticationPath());
98 |
99 | assertFalse(request.isCerts()); // Only verify specific parameter
100 | }
101 |
102 | /** Invocing jarsigner with the -certs parameter */
103 | @Test
104 | public void testCertsTrue() throws Exception {
105 | Artifact mainArtifact = TestArtifacts.createJarArtifact(dummyMavenProjectDir, "my-project.jar");
106 | when(project.getArtifact()).thenReturn(mainArtifact);
107 | when(jarSigner.execute(any(JarSignerVerifyRequest.class))).thenReturn(RESULT_OK);
108 | configuration.put("certs", "true");
109 | JarsignerVerifyMojo mojo = mojoTestCreator.configure(configuration);
110 |
111 | mojo.execute();
112 |
113 | verify(jarSigner).execute(argThat(request -> ((JarSignerVerifyRequest) request).isCerts()));
114 | }
115 |
116 | /** When the jarsigner signing verification check tells there is a problem with the signing of the file */
117 | @Test
118 | public void testVerifyFailure() throws Exception {
119 | Artifact mainArtifact = TestArtifacts.createJarArtifact(dummyMavenProjectDir, "my-project.jar");
120 | when(project.getArtifact()).thenReturn(mainArtifact);
121 | when(jarSigner.execute(any(JarSignerVerifyRequest.class))).thenReturn(RESULT_ERROR);
122 | JarsignerVerifyMojo mojo = mojoTestCreator.configure(configuration);
123 |
124 | MojoExecutionException mojoException = assertThrows(MojoExecutionException.class, () -> {
125 | mojo.execute();
126 | });
127 | assertThat(mojoException.getMessage(), containsString(String.valueOf(RESULT_ERROR.getExitCode())));
128 | assertThat(
129 | mojoException.getMessage(),
130 | containsString(RESULT_ERROR.getCommandline().toString()));
131 | }
132 |
133 | /** When setting errorWhenNotSigned, for file that has existing signing (should not fail) */
134 | @Test
135 | public void testErrorWhenNotSignedOnExistingSigning() throws Exception {
136 | File signedJar = TestArtifacts.createDummySignedJarFile(new File(dummyMavenProjectDir, "my-project.jar"));
137 | Artifact mainArtifact = TestArtifacts.createArtifact(signedJar);
138 | when(project.getArtifact()).thenReturn(mainArtifact);
139 | when(jarSigner.execute(any(JarSignerVerifyRequest.class))).thenReturn(RESULT_OK);
140 | configuration.put("errorWhenNotSigned", "true");
141 |
142 | JarsignerVerifyMojo mojo = mojoTestCreator.configure(configuration);
143 |
144 | mojo.execute();
145 |
146 | verify(jarSigner).execute(MockitoHamcrest.argThat(RequestMatchers.hasFileName("my-project.jar")));
147 | }
148 |
149 | /** When setting errorWhenNotSigned, for file that does not have existing signing (should fail) */
150 | @Test
151 | public void testErrorWhenNotSignedOnNonExistingSigning() throws Exception {
152 | Artifact mainArtifact = TestArtifacts.createJarArtifact(dummyMavenProjectDir, "my-project.jar");
153 | when(project.getArtifact()).thenReturn(mainArtifact);
154 | when(jarSigner.execute(any(JarSignerVerifyRequest.class))).thenReturn(RESULT_OK);
155 | configuration.put("errorWhenNotSigned", "true");
156 |
157 | JarsignerVerifyMojo mojo = mojoTestCreator.configure(configuration);
158 |
159 | MojoExecutionException mojoException = assertThrows(MojoExecutionException.class, () -> {
160 | mojo.execute();
161 | });
162 | assertThat(
163 | mojoException.getMessage(),
164 | containsString(mainArtifact.getFile().getPath()));
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/MojoTestCreator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.lang.reflect.Field;
23 | import java.util.ArrayList;
24 | import java.util.Arrays;
25 | import java.util.List;
26 | import java.util.Map;
27 | import java.util.regex.Matcher;
28 | import java.util.regex.Pattern;
29 |
30 | import org.apache.maven.plugin.Mojo;
31 | import org.apache.maven.plugin.logging.Log;
32 | import org.apache.maven.plugins.jarsigner.JarsignerSignMojo.WaitStrategy;
33 | import org.apache.maven.project.MavenProject;
34 | import org.apache.maven.shared.jarsigner.JarSigner;
35 | import org.apache.maven.toolchain.ToolchainManager;
36 | import org.slf4j.Logger;
37 | import org.slf4j.LoggerFactory;
38 | import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
39 |
40 | /**
41 | * Creates and configures a Mojo instance to be used in testing.
42 | *
43 | * @param The type of Mojo
44 | */
45 | public class MojoTestCreator {
46 |
47 | private final Logger logger = LoggerFactory.getLogger(MojoTestCreator.class);
48 |
49 | private final Class clazz;
50 | private final MavenProject project;
51 | private final File projectDir;
52 | private final JarSigner jarSigner;
53 | private ToolchainManager toolchainManager;
54 | private SecDispatcher securityDispatcher;
55 | private WaitStrategy waitStrategy;
56 | private Log log;
57 | private List fields;
58 |
59 | public MojoTestCreator(Class clazz, MavenProject project, File projectDir, JarSigner jarSigner)
60 | throws Exception {
61 | this.clazz = clazz;
62 | this.project = project;
63 | this.projectDir = projectDir;
64 | this.jarSigner = jarSigner;
65 |
66 | securityDispatcher = str -> str; // Simple SecDispatcher that only returns parameter
67 | fields = getAllFields(clazz);
68 | }
69 |
70 | public void setToolchainManager(ToolchainManager toolchainManager) {
71 | this.toolchainManager = toolchainManager;
72 | }
73 |
74 | public void setSecDispatcher(SecDispatcher securityDispatcher) {
75 | this.securityDispatcher = securityDispatcher;
76 | }
77 |
78 | public void setWaitStrategy(WaitStrategy waitStrategy) {
79 | this.waitStrategy = waitStrategy;
80 | }
81 |
82 | public void setLog(Log log) {
83 | this.log = log;
84 | }
85 |
86 | /**
87 | * Creates and configures the Mojo instance.
88 | *
89 | * @param configuration user supplied configuration
90 | */
91 | public T configure(Map configuration, Class>... parameterTypes) throws Exception {
92 | T mojo = clazz.getDeclaredConstructor(parameterTypes).newInstance();
93 | setDefaultValues(mojo);
94 |
95 | setAttribute(mojo, "project", project);
96 | setAttribute(mojo, "jarSigner", jarSigner);
97 | setAttribute(mojo, "securityDispatcher", securityDispatcher);
98 | if (toolchainManager != null) {
99 | setAttribute(mojo, "toolchainManager", toolchainManager);
100 | }
101 | if (waitStrategy != null) {
102 | ((JarsignerSignMojo) mojo).setWaitStrategy(waitStrategy);
103 | }
104 | if (log != null) {
105 | mojo.setLog(log);
106 | }
107 |
108 | for (Map.Entry entry : configuration.entrySet()) {
109 | Field field = getField(mojo, entry.getKey());
110 | setFieldByStringValue(mojo, field, entry.getValue());
111 | }
112 |
113 | return mojo;
114 | }
115 |
116 | private void setFieldByStringValue(Object instance, Field field, String stringValue) throws Exception {
117 | field.setAccessible(true);
118 | Class> fieldType = field.getType();
119 | if (fieldType.equals(String.class)) {
120 | field.set(instance, stringValue);
121 | } else if (fieldType.equals(int.class)) {
122 | field.setInt(instance, Integer.parseInt(stringValue));
123 | } else if (fieldType.equals(boolean.class)) {
124 | field.setBoolean(instance, Boolean.parseBoolean(stringValue));
125 | } else if (fieldType.equals(File.class)) {
126 | field.set(instance, new File(stringValue));
127 | } else if (fieldType.equals(String[].class)) {
128 | if (stringValue.isEmpty()) {
129 | // Maven defaults to empty list if no default value exists
130 | field.set(instance, new String[0]);
131 | } else {
132 | String[] values = stringValue.split(",");
133 | field.set(instance, values);
134 | }
135 | } else {
136 | if (!stringValue.startsWith("${")) {
137 | logger.warn(
138 | "Not implemented support to set of field of type {} to value {}",
139 | fieldType.getSimpleName(),
140 | stringValue);
141 | }
142 | }
143 | }
144 |
145 | private Field getField(Object instance, String fieldName) {
146 | return fields.stream()
147 | .filter(f -> f.getName().equals(fieldName))
148 | .findFirst()
149 | .orElseThrow(() -> new RuntimeException("Could not find field " + fieldName + " in class "
150 | + instance.getClass().getName()));
151 | }
152 |
153 | private void setAttribute(Object instance, String fieldName, Object value) throws Exception {
154 | Field field = getField(instance, fieldName);
155 | field.setAccessible(true);
156 | field.set(instance, value);
157 | }
158 |
159 | private void setDefaultValues(Mojo mojo) throws Exception {
160 | Map defaultConfiguration = PluginXmlParser.getMojoDefaultConfiguration(mojo.getClass());
161 | for (String parameterName : defaultConfiguration.keySet()) {
162 | String defaultValue = defaultConfiguration.get(parameterName);
163 | defaultValue = substituteParameterValueVariables(defaultValue);
164 | Field field = getField(mojo, parameterName);
165 | setFieldByStringValue(mojo, field, defaultValue.toString());
166 | }
167 | }
168 |
169 | private String substituteParameterValueVariables(String parameterValue) {
170 | parameterValue = parameterValue.replaceAll(
171 | Pattern.quote("${project.basedir}"), Matcher.quoteReplacement(projectDir.getPath()));
172 | return parameterValue;
173 | }
174 |
175 | static List getAllFields(Class> clazz) {
176 | List fields = new ArrayList<>();
177 | Class> currentClazz = clazz;
178 | while (currentClazz != null) {
179 | fields.addAll(Arrays.asList(currentClazz.getDeclaredFields()));
180 | currentClazz = currentClazz.getSuperclass();
181 | }
182 | return fields;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/PluginXmlParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import javax.xml.parsers.DocumentBuilder;
22 | import javax.xml.parsers.DocumentBuilderFactory;
23 |
24 | import java.io.InputStream;
25 | import java.util.LinkedHashMap;
26 | import java.util.Map;
27 |
28 | import org.apache.maven.plugin.Mojo;
29 | import org.w3c.dom.Document;
30 | import org.w3c.dom.Element;
31 | import org.w3c.dom.Node;
32 | import org.w3c.dom.NodeList;
33 |
34 | /**
35 | * Parser of the generated META-INF/maven/plugin.xml for this project. The plugin.xml contains all mojos their
36 | * configuration parameters along with default values.
37 | */
38 | public class PluginXmlParser {
39 | private static final String MOJO_IMPLEMENTATION_TAG = "implementation";
40 | private static final String MOJO_TAG = "mojo";
41 | private static final String CONF_DEFAULT_VALUE = "default-value";
42 | private static final String PLUGIN_XML_PATH = "META-INF/maven/plugin.xml";
43 |
44 | public static Map getMojoDefaultConfiguration(Class extends Mojo> mojoClass) throws Exception {
45 | Map defaultConfiguration = new LinkedHashMap<>();
46 | InputStream inputStream = PluginXmlParser.class.getClassLoader().getResourceAsStream(PLUGIN_XML_PATH);
47 | DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
48 | DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
49 | Document doc = dBuilder.parse(inputStream);
50 | doc.getDocumentElement().normalize();
51 |
52 | Element mojoElement = findMojoByClass(doc, mojoClass.getName());
53 | if (mojoElement == null) {
54 | throw new RuntimeException("Mojo not found for class: " + mojoClass.getName());
55 | }
56 |
57 | Element configurationElement =
58 | (Element) mojoElement.getElementsByTagName("configuration").item(0);
59 | NodeList configurationList = configurationElement.getChildNodes();
60 | for (int i = 0; i < configurationList.getLength(); i++) {
61 | Node child = configurationList.item(i);
62 | if (child.getNodeType() != Node.ELEMENT_NODE) {
63 | continue;
64 | }
65 | configurationElement = (Element) child;
66 | String configurationParameterName = configurationElement.getTagName();
67 |
68 | if (configurationElement.hasAttribute(CONF_DEFAULT_VALUE)) {
69 | String defaultValue = configurationElement.getAttribute(CONF_DEFAULT_VALUE);
70 | defaultConfiguration.put(configurationParameterName, defaultValue);
71 | } else {
72 | if (configurationElement.hasAttribute("implementation")) {
73 | String implementation = configurationElement.getAttribute("implementation");
74 | // String arrays are per default set to empty array if user does not configure them
75 | if ("java.lang.String[]".equals(implementation)) {
76 | defaultConfiguration.put(configurationParameterName, "");
77 | }
78 | }
79 | }
80 | }
81 | return defaultConfiguration;
82 | }
83 |
84 | /** Searches in every mojo tag for an implementation tag matching the class name */
85 | private static Element findMojoByClass(Document doc, String className) {
86 | NodeList mojoList = doc.getElementsByTagName(MOJO_TAG);
87 | for (int i = 0; i < mojoList.getLength(); i++) {
88 | Element mojoElement = (Element) mojoList.item(i);
89 | String mojoClass = getTextContent(mojoElement, MOJO_IMPLEMENTATION_TAG);
90 | if (mojoClass.equals(className)) {
91 | return mojoElement;
92 | }
93 | }
94 | return null;
95 | }
96 |
97 | private static String getTextContent(Element parentElement, String tagName) {
98 | NodeList nodeList = parentElement.getElementsByTagName(tagName);
99 | if (nodeList.getLength() > 0) {
100 | return nodeList.item(0).getTextContent();
101 | }
102 | return null;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/RequestMatchers.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.util.Arrays;
22 | import java.util.List;
23 | import java.util.function.Predicate;
24 |
25 | import org.apache.maven.shared.jarsigner.AbstractJarSignerRequest;
26 | import org.apache.maven.shared.jarsigner.JarSignerSignRequest;
27 | import org.hamcrest.Description;
28 | import org.hamcrest.TypeSafeMatcher;
29 |
30 | /**
31 | * Hamcrest matcher(s) to match properties on a JarSignerRequest request instances
32 | */
33 | class RequestMatchers {
34 |
35 | /** Matcher for parameters common for JarSignerRequest instances */
36 | private static class AbstractJarSignerRequestMatcher
37 | extends TypeSafeMatcher {
38 | private final String predicateDescription;
39 | private final Object value;
40 | private final Predicate predicate;
41 |
42 | private AbstractJarSignerRequestMatcher(
43 | String predicateDescription, Object value, Predicate predicate) {
44 | this.predicateDescription = predicateDescription;
45 | this.value = value;
46 | this.predicate = predicate;
47 | }
48 |
49 | @Override
50 | protected boolean matchesSafely(AbstractJarSignerRequest request) {
51 | return predicate.test(request);
52 | }
53 |
54 | @Override
55 | public void describeTo(Description description) {
56 | description
57 | .appendText("request that ")
58 | .appendText(predicateDescription)
59 | .appendValue(value);
60 | }
61 | }
62 |
63 | /** Matcher for parameters specific to JarSignerSignRequest instances */
64 | private static class JarSignerSignRequestMatcher extends TypeSafeMatcher {
65 | private final String predicateDescription;
66 | private final Object value;
67 | private final Predicate predicate;
68 |
69 | private JarSignerSignRequestMatcher(
70 | String predicateDescription, Object value, Predicate predicate) {
71 | this.predicateDescription = predicateDescription;
72 | this.value = value;
73 | this.predicate = predicate;
74 | }
75 |
76 | @Override
77 | protected boolean matchesSafely(JarSignerSignRequest request) {
78 | return predicate.test(request);
79 | }
80 |
81 | @Override
82 | public void describeTo(Description description) {
83 | description
84 | .appendText("request that ")
85 | .appendText(predicateDescription)
86 | .appendValue(value);
87 | }
88 | }
89 |
90 | /** Create a matcher that matches when the request is using a specific file name for the archive */
91 | static TypeSafeMatcher hasFileName(String expectedFileName) {
92 | return new AbstractJarSignerRequestMatcher(
93 | "has archive file name ",
94 | expectedFileName,
95 | request -> request.getArchive().getPath().endsWith(expectedFileName));
96 | }
97 |
98 | static TypeSafeMatcher hasAlias(String alias) {
99 | return new AbstractJarSignerRequestMatcher(
100 | "has alias ", alias, request -> request.getAlias().equals(alias));
101 | }
102 |
103 | static TypeSafeMatcher hasArguments(String[] arguments) {
104 | return new AbstractJarSignerRequestMatcher("has arguments ", arguments, request -> {
105 | List haystack = Arrays.asList(request.getArguments());
106 | for (String argumentNeedle : arguments) {
107 | if (!haystack.contains(argumentNeedle)) {
108 | return false;
109 | }
110 | }
111 | return true;
112 | });
113 | }
114 |
115 | static TypeSafeMatcher hasKeystore(String keystore) {
116 | return new AbstractJarSignerRequestMatcher(
117 | "has keystore ", keystore, request -> request.getKeystore().equals(keystore));
118 | }
119 |
120 | static TypeSafeMatcher hasMaxMemory(String maxMemory) {
121 | return new AbstractJarSignerRequestMatcher(
122 | "has maxMemory ", maxMemory, request -> request.getMaxMemory().equals(maxMemory));
123 | }
124 |
125 | static TypeSafeMatcher hasProtectedAuthenticationPath(
126 | boolean protectedAuthenticationPath) {
127 | return new AbstractJarSignerRequestMatcher(
128 | "has protectedAuthenticationPath ",
129 | protectedAuthenticationPath,
130 | request -> request.isProtectedAuthenticationPath() == protectedAuthenticationPath);
131 | }
132 |
133 | static TypeSafeMatcher hasProviderArg(String providerArg) {
134 | return new AbstractJarSignerRequestMatcher(
135 | "has providerArg ", providerArg, request -> request.getProviderArg()
136 | .equals(providerArg));
137 | }
138 |
139 | static TypeSafeMatcher hasProviderClass(String providerClass) {
140 | return new AbstractJarSignerRequestMatcher(
141 | "has providerClass ", providerClass, request -> request.getProviderClass()
142 | .equals(providerClass));
143 | }
144 |
145 | static TypeSafeMatcher hasProviderName(String providerName) {
146 | return new AbstractJarSignerRequestMatcher(
147 | "has providerName ", providerName, request -> request.getProviderName()
148 | .equals(providerName));
149 | }
150 |
151 | static TypeSafeMatcher hasStorepass(String storepass) {
152 | return new AbstractJarSignerRequestMatcher(
153 | "has storepass ", storepass, request -> request.getStorepass().equals(storepass));
154 | }
155 |
156 | static TypeSafeMatcher hasStoretype(String storetype) {
157 | return new AbstractJarSignerRequestMatcher(
158 | "has storetype ", storetype, request -> request.getStoretype().equals(storetype));
159 | }
160 |
161 | static TypeSafeMatcher hasVerbose(boolean verbose) {
162 | return new AbstractJarSignerRequestMatcher(
163 | "has verbose ", verbose, request -> request.isVerbose() == verbose);
164 | }
165 |
166 | /* ************************************ JarSignerSignRequest specific matchers ************************************/
167 |
168 | static TypeSafeMatcher hasKeypass(String keypass) {
169 | return new JarSignerSignRequestMatcher(
170 | "has keypass ", keypass, request -> request.getKeypass().equals(keypass));
171 | }
172 |
173 | static TypeSafeMatcher hasSigfile(String sigfile) {
174 | return new JarSignerSignRequestMatcher(
175 | "has sigfile ", sigfile, request -> request.getSigfile().equals(sigfile));
176 | }
177 |
178 | static TypeSafeMatcher hasTsa(String tsa) {
179 | return new JarSignerSignRequestMatcher(
180 | "has tsa ", tsa, request -> request.getTsaLocation().equals(tsa));
181 | }
182 |
183 | static TypeSafeMatcher hasTsacert(String tsacert) {
184 | return new JarSignerSignRequestMatcher(
185 | "has tsacert ", tsacert, request -> request.getTsaAlias().equals(tsacert));
186 | }
187 |
188 | static TypeSafeMatcher hasTsaPolicyid(String tsapolicyid) {
189 | return new JarSignerSignRequestMatcher("has tsapolicyid ", tsapolicyid, request -> request.getTsapolicyid()
190 | .equals(tsapolicyid));
191 | }
192 |
193 | static TypeSafeMatcher hasTsaDigestalg(String tsadigestalg) {
194 | return new JarSignerSignRequestMatcher("has tsadigestalg ", tsadigestalg, request -> request.getTsadigestalg()
195 | .equals(tsadigestalg));
196 | }
197 |
198 | static TypeSafeMatcher hasCertchain(String certchain) {
199 | return new JarSignerSignRequestMatcher("has certchain ", certchain, request -> request.getCertchain()
200 | .getPath()
201 | .equals(certchain));
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/TestArtifacts.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.io.File;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.nio.file.Files;
25 | import java.util.zip.ZipEntry;
26 | import java.util.zip.ZipOutputStream;
27 |
28 | import org.apache.maven.artifact.Artifact;
29 | import org.apache.maven.artifact.DefaultArtifact;
30 |
31 | /**
32 | * Test utility class to create Artifact objects, jar file or other files that Maven attaches to a project
33 | */
34 | class TestArtifacts {
35 | static final String TEST_GROUPID = "org.test-group";
36 | static final String TEST_ARTIFACTID = "test-artifact";
37 | static final String TEST_VERSION = "9.10.2";
38 | static final String TEST_TYPE = "jar";
39 | static final String TEST_CLASSIFIER = "";
40 |
41 | static Artifact createArtifact(File file) throws IOException {
42 | return createArtifact(file, TEST_TYPE, TEST_CLASSIFIER);
43 | }
44 |
45 | static Artifact createArtifact(File file, String type, String classifier) throws IOException {
46 | Artifact artifact = new DefaultArtifact(
47 | TEST_GROUPID, TEST_ARTIFACTID, TEST_VERSION, Artifact.SCOPE_COMPILE, type, classifier, null);
48 | artifact.setFile(file);
49 | return artifact;
50 | }
51 |
52 | static Artifact createJarArtifact(File directory, String filename) throws IOException {
53 | return createJarArtifact(directory, filename, TEST_CLASSIFIER);
54 | }
55 |
56 | public static Artifact createJarArtifact(File directory, String filename, String classifier) throws IOException {
57 | return createJarArtifact(directory, filename, classifier, TEST_TYPE);
58 | }
59 |
60 | public static Artifact createJarArtifact(File directory, String filename, String classifier, String type)
61 | throws IOException {
62 | File file = new File(directory, filename);
63 | createDummyZipFile(file);
64 | return createArtifact(file, type, classifier);
65 | }
66 |
67 | static Artifact createPomArtifact(File directory, String filename) throws IOException {
68 | File file = new File(directory, filename);
69 | createDummyXMLFile(file);
70 | return createArtifact(file, TEST_TYPE, "");
71 | }
72 |
73 | /** Create a dummy JAR/ZIP file, enough to pass ZipInputStream.getNextEntry() */
74 | static File createDummyZipFile(File zipFile) throws IOException {
75 | try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile))) {
76 | ZipEntry entry = new ZipEntry("dummy-entry.txt");
77 | zipOutputStream.putNextEntry(entry);
78 | }
79 | return zipFile;
80 | }
81 |
82 | /** Create a dummy signed JAR, enough to pass JarSignerUtil.isArchiveSigned() */
83 | static File createDummySignedJarFile(File jarFile) throws IOException {
84 | try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(jarFile))) {
85 | ZipEntry entry = new ZipEntry("dummy-entry.txt");
86 | zipOutputStream.putNextEntry(entry);
87 | zipOutputStream.putNextEntry(new ZipEntry("META-INF/dummy.RSA"));
88 | }
89 |
90 | return jarFile;
91 | }
92 |
93 | /** Create a dummy XML file, for example to simulate a pom.xml file */
94 | static File createDummyXMLFile(File xmlFile) throws IOException {
95 | Files.write(xmlFile.toPath(), "".getBytes());
96 | return xmlFile;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/TestJavaToolResults.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import org.apache.maven.shared.utils.cli.Commandline;
22 | import org.apache.maven.shared.utils.cli.javatool.JavaToolResult;
23 | import org.apache.maven.shared.utils.cli.shell.Shell;
24 |
25 | /**
26 | * Results from an invocation to {@link org.apache.maven.shared.utils.cli.javatool.JavaTool} to be used in tests.
27 | */
28 | class TestJavaToolResults {
29 | static final JavaToolResult RESULT_OK = createOk();
30 | static final JavaToolResult RESULT_ERROR = createError();
31 |
32 | private static JavaToolResult createOk() {
33 | JavaToolResult result = new JavaToolResult();
34 | result.setExitCode(0);
35 | result.setExecutionException(null);
36 | result.setCommandline(getSimpleCommandline());
37 | return result;
38 | }
39 |
40 | private static JavaToolResult createError() {
41 | JavaToolResult result = new JavaToolResult();
42 | result.setExitCode(1);
43 | result.setExecutionException(null);
44 | result.setCommandline(getSimpleCommandline());
45 | return result;
46 | }
47 |
48 | private static Commandline getSimpleCommandline() {
49 | Shell shell = new Shell();
50 | Commandline commandline = new Commandline(shell);
51 | commandline.setExecutable("jarsigner");
52 | commandline.addArguments("my-project.jar", "myalias");
53 | return commandline;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/java/org/apache/maven/plugins/jarsigner/TsaSelectorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.apache.maven.plugins.jarsigner;
20 |
21 | import java.util.concurrent.CountDownLatch;
22 | import java.util.concurrent.ExecutorService;
23 | import java.util.concurrent.Executors;
24 | import java.util.concurrent.Semaphore;
25 | import java.util.concurrent.TimeUnit;
26 | import java.util.concurrent.atomic.AtomicReference;
27 |
28 | import org.apache.maven.plugins.jarsigner.TsaSelector.TsaServer;
29 | import org.junit.Test;
30 |
31 | import static org.junit.Assert.*;
32 |
33 | public class TsaSelectorTest {
34 | private static final String[] EMPTY = new String[0];
35 | private TsaSelector tsaSelector;
36 | private TsaServer tsaServer;
37 | private ExecutorService executor;
38 |
39 | @Test
40 | public void testNullInit() {
41 | tsaSelector = new TsaSelector(EMPTY, EMPTY, EMPTY, null);
42 | tsaServer = tsaSelector.getServer();
43 | assertNull(tsaServer.getTsaUrl());
44 | assertNull(tsaServer.getTsaAlias());
45 | assertNull(tsaServer.getTsaPolicyId());
46 | assertNull(tsaServer.getTsaDigestAlg());
47 |
48 | // Make sure "next" server also contains null values
49 | tsaServer = tsaSelector.getServer();
50 | assertNull(tsaServer.getTsaUrl());
51 | assertNull(tsaServer.getTsaAlias());
52 | assertNull(tsaServer.getTsaPolicyId());
53 | assertNull(tsaServer.getTsaDigestAlg());
54 | }
55 |
56 | @Test
57 | public void testFailureCount() {
58 | tsaSelector = new TsaSelector(
59 | new String[] {"http://url1.com", "http://url2.com", "http://url3.com"}, EMPTY, EMPTY, null);
60 |
61 | tsaServer = tsaSelector.getServer();
62 | assertEquals("http://url1.com", tsaServer.getTsaUrl());
63 | assertNull(tsaServer.getTsaAlias());
64 | assertNull(tsaServer.getTsaPolicyId());
65 | assertNull(tsaServer.getTsaDigestAlg());
66 |
67 | tsaSelector.registerFailure();
68 |
69 | tsaServer = tsaSelector.getServer();
70 | assertEquals("http://url2.com", tsaServer.getTsaUrl());
71 | assertNull(tsaServer.getTsaAlias());
72 | assertNull(tsaServer.getTsaPolicyId());
73 | assertNull(tsaServer.getTsaDigestAlg());
74 |
75 | // Should get same server again
76 | tsaServer = tsaSelector.getServer();
77 | assertEquals("http://url2.com", tsaServer.getTsaUrl());
78 | assertNull(tsaServer.getTsaAlias());
79 | assertNull(tsaServer.getTsaPolicyId());
80 | assertNull(tsaServer.getTsaDigestAlg());
81 | }
82 |
83 | @Test(timeout = 30000)
84 | public void testMultiThreadedScenario() throws InterruptedException {
85 | executor = Executors.newFixedThreadPool(2);
86 |
87 | tsaSelector = new TsaSelector(
88 | new String[] {"http://url1.com", "http://url2.com", "http://url3.com"}, EMPTY, EMPTY, null);
89 |
90 | // Register a single failure on the first URL so that the threads will use URL 2
91 | TsaServer serverThreadMain = tsaSelector.getServer();
92 | tsaSelector.registerFailure();
93 |
94 | CountDownLatch doneSignal = new CountDownLatch(2); // Indication that both threads has gotten a server
95 | Semaphore semaphore = new Semaphore(0); // When the threads may continue executing after gotten a server
96 |
97 | AtomicReference serverThread1 = new AtomicReference<>();
98 | AtomicReference serverThread2 = new AtomicReference<>();
99 | executor.submit(() -> {
100 | serverThread1.set(tsaSelector.getServer());
101 | doneSignal.countDown();
102 | semaphore.acquireUninterruptibly();
103 | tsaSelector.registerFailure();
104 | });
105 | executor.submit(() -> {
106 | serverThread2.set(tsaSelector.getServer());
107 | doneSignal.countDown();
108 | semaphore.acquireUninterruptibly();
109 | tsaSelector.registerFailure();
110 | });
111 |
112 | doneSignal.await(); // Wait until both threads has gotten an TsaServer
113 | semaphore.release(2); // Release both threads waiting for the semaphore
114 |
115 | executor.shutdown();
116 | executor.awaitTermination(10, TimeUnit.SECONDS);
117 |
118 | assertEquals("http://url1.com", serverThreadMain.getTsaUrl());
119 | assertEquals("http://url2.com", serverThread1.get().getTsaUrl());
120 | assertEquals("http://url2.com", serverThread2.get().getTsaUrl());
121 |
122 | // The best URL is now number 3
123 | assertEquals("http://url3.com", tsaSelector.getServer().getTsaUrl());
124 |
125 | // Trigger a new failure, now URL 1 is best again.
126 | tsaSelector.registerFailure();
127 | assertEquals("http://url1.com", tsaSelector.getServer().getTsaUrl());
128 | }
129 |
130 | @Test
131 | public void testDigestAlgoritm() {
132 | tsaSelector = new TsaSelector(
133 | new String[] {"http://url1.com", "http://url2.com", "http://url3.com"}, EMPTY, EMPTY, "SHA-512");
134 | tsaServer = tsaSelector.getServer();
135 | assertEquals("http://url1.com", tsaServer.getTsaUrl());
136 | assertNull(tsaServer.getTsaAlias());
137 | assertNull(tsaServer.getTsaPolicyId());
138 | assertEquals("SHA-512", tsaServer.getTsaDigestAlg());
139 |
140 | // Make sure that the next URL has the same digest algorithm
141 | tsaSelector.registerFailure();
142 | tsaServer = tsaSelector.getServer();
143 | assertEquals("http://url2.com", tsaServer.getTsaUrl());
144 | assertNull(tsaServer.getTsaAlias());
145 | assertNull(tsaServer.getTsaPolicyId());
146 | assertEquals("SHA-512", tsaServer.getTsaDigestAlg());
147 | }
148 |
149 | @Test
150 | public void testKeyStoreAliasAndOid() {
151 | tsaSelector = new TsaSelector(EMPTY, new String[] {"alias1", "alias2"}, new String[] {"1.1", "1.2"}, null);
152 | tsaServer = tsaSelector.getServer();
153 | assertNull(tsaServer.getTsaUrl());
154 | assertEquals("alias1", tsaServer.getTsaAlias());
155 | assertEquals("1.1", tsaServer.getTsaPolicyId());
156 |
157 | tsaSelector.registerFailure();
158 | tsaServer = tsaSelector.getServer();
159 | assertNull(tsaServer.getTsaUrl());
160 | assertEquals("alias2", tsaServer.getTsaAlias());
161 | assertEquals("1.2", tsaServer.getTsaPolicyId());
162 | }
163 |
164 | @Test
165 | public void testFailureRegistrationWithoutCurrent() {
166 | tsaSelector = new TsaSelector(
167 | new String[] {"http://url1.com"}, new String[] {"alias1"}, new String[] {"1.1"}, "SHA-384");
168 | tsaSelector.registerFailure(); // Should not throw any exception
169 |
170 | // Make sure further execution works
171 | tsaServer = tsaSelector.getServer();
172 | assertEquals("http://url1.com", tsaServer.getTsaUrl());
173 | assertEquals("alias1", tsaServer.getTsaAlias());
174 | assertEquals("1.1", tsaServer.getTsaPolicyId());
175 | assertEquals("SHA-384", tsaServer.getTsaDigestAlg());
176 | }
177 | }
178 |
--------------------------------------------------------------------------------