This is an automated email from the ASF dual-hosted git repository. slachiewicz pushed a commit to branch MJARSIGNER-41 in repository https://gitbox.apache.org/repos/asf/maven-jarsigner-plugin.git
commit 357edd5566983d9924ca04fd0f4a6fdd525b9d3c Author: Lasse Lindqvist <lasse.k.lindqv...@gmail.com> AuthorDate: Wed Dec 19 21:18:10 2018 +0200 [MJARSIGNER-41] Implement maxTries parameter maxTries lets the plugin try signing multiple times if first tries fail. Useful when used with a Time Stamp Authority. Default is 1 so backwards compatibility is fully kept. --- pom.xml | 19 +++++ .../plugins/jarsigner/AbstractJarsignerMojo.java | 62 +++++++++++--- .../jarsigner/AbstractJarsignerMojoTest.java | 96 ++++++++++++++++++++++ 3 files changed, 164 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index c1cc725..795be8b 100644 --- a/pom.xml +++ b/pom.xml @@ -117,6 +117,18 @@ under the License. <artifactId>maven-jarsigner</artifactId> <version>3.0.0</version> </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.28.2</version><!-- 2.x for Java 7 --> + <scope>test</scope> + </dependency> </dependencies> <build> @@ -143,6 +155,13 @@ under the License. </plugin> </plugins> </pluginManagement> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.8.5</version> + </plugin> + </plugins> </build> <profiles> diff --git a/src/main/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojo.java b/src/main/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojo.java index 92d3a8f..690d4cd 100644 --- a/src/main/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojo.java +++ b/src/main/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojo.java @@ -254,11 +254,31 @@ public abstract class AbstractJarsignerMojo @Component( hint = "mng-4384" ) private SecDispatcher securityDispatcher; + /** + * How many times to try to sign or verify a jar (assuming each previous attempt is a failure). + * + * This option may be desirable if you are using a Time Stamp Authority, + * and your network conditions cause intermittent failures. + * + * The default is "1" for one attempt. + * + * Less than 0 and "0" we be treated as 1 (because using "skip" is accepted and encouraged, + * and an infinite retry loop is undesirable). + * + * @since 1.4 + */ + @Parameter( property = "jarsigner.maxTries", defaultValue = "1" ) + private int maxTries; + public final void execute() throws MojoExecutionException { if ( !this.skip ) { + if ( maxTries <= 0 ) + { + maxTries = 1; + } Toolchain toolchain = getToolchain(); if ( toolchain != null ) @@ -556,19 +576,7 @@ public abstract class AbstractJarsignerMojo try { - JavaToolResult result = jarSigner.execute( request ); - - Commandline commandLine = result.getCommandline(); - - int resultCode = result.getExitCode(); - - if ( resultCode != 0 ) - { - // CHECKSTYLE_OFF: LineLength - throw new MojoExecutionException( getMessage( "failure", getCommandlineInfo( commandLine ), resultCode ) ); - // CHECKSTYLE_ON: LineLength - } - + sign( jarSigner, request, maxTries ); } catch ( JavaToolException e ) { @@ -576,6 +584,34 @@ public abstract class AbstractJarsignerMojo } } + /** + * Attempts signing with a maximum number of maxTries times. If all attempts fail, MojoExecutionException is thrown. + * If java tool invocation could not be created, a JavaToolException will be thrown. + * + * @param jarSigner the JarSigner + * @param request the JarSignerRequest + * @param maxTries a positive integer + * @throws JavaToolException + * @throws MojoExecutionException + */ + void sign( JarSigner jarSigner, JarSignerRequest request, int maxTries ) + throws JavaToolException, MojoExecutionException + { + Commandline commandLine = null; + int resultCode = 0; + for ( int attempt = 0; attempt < maxTries; attempt++ ) + { + JavaToolResult result = jarSigner.execute( request ); + resultCode = result.getExitCode(); + commandLine = result.getCommandline(); + if ( resultCode == 0 ) + { + return; + } + } + throw new MojoExecutionException( getMessage( "failure", getCommandlineInfo( commandLine ), resultCode ) ); + } + protected String decrypt( String encoded ) throws MojoExecutionException { diff --git a/src/test/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojoTest.java b/src/test/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojoTest.java new file mode 100644 index 0000000..984cfee --- /dev/null +++ b/src/test/java/org/apache/maven/plugins/jarsigner/AbstractJarsignerMojoTest.java @@ -0,0 +1,96 @@ +package org.apache.maven.plugins.jarsigner; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.shared.jarsigner.JarSigner; +import org.apache.maven.shared.jarsigner.JarSignerRequest; +import org.apache.maven.shared.utils.cli.javatool.JavaToolException; +import org.apache.maven.shared.utils.cli.javatool.JavaToolResult; +import org.junit.Test; + +import static org.mockito.Mockito.*; + +public class AbstractJarsignerMojoTest +{ + @Test + public void testSignSuccessOnFirst() throws MojoExecutionException, JavaToolException + { + AbstractJarsignerMojo mojo = mock( AbstractJarsignerMojo.class ); + JarSigner jarSigner = mock( JarSigner.class ); + JarSignerRequest request = mock( JarSignerRequest.class ); + doCallRealMethod().when( mojo ).sign( jarSigner, request, 1 ); + JavaToolResult result = new JavaToolResult(); + result.setExitCode( 0 ); + when( jarSigner.execute( request ) ).thenReturn( result ); + + mojo.sign( jarSigner, request, 1 ); + } + + @Test( expected = MojoExecutionException.class ) + public void testSignFailureOnFirst() throws MojoExecutionException, JavaToolException + { + AbstractJarsignerMojo mojo = mock( AbstractJarsignerMojo.class ); + JarSigner jarSigner = mock( JarSigner.class ); + JarSignerRequest request = mock( JarSignerRequest.class ); + doCallRealMethod().when( mojo ).sign( jarSigner, request, 1 ); + JavaToolResult result = new JavaToolResult(); + result.setExitCode( 1 ); + when( jarSigner.execute( request ) ).thenReturn( result ); + + mojo.sign( jarSigner, request, 1 ); + } + + @Test + public void testSignFailureOnFirstSuccessOnSecond() throws MojoExecutionException, JavaToolException + { + AbstractJarsignerMojo mojo = mock( AbstractJarsignerMojo.class ); + JarSigner jarSigner = mock( JarSigner.class ); + JarSignerRequest request = mock( JarSignerRequest.class ); + doCallRealMethod().when( mojo ).sign( jarSigner, request, 2 ); + JavaToolResult result1 = new JavaToolResult(); + result1.setExitCode( 1 ); + JavaToolResult result2 = new JavaToolResult(); + result2.setExitCode( 0 ); + when( jarSigner.execute( request ) ) + .thenReturn( result1 ) + .thenReturn( result2 ); + + mojo.sign( jarSigner, request, 2 ); + } + + @Test( expected = MojoExecutionException.class ) + public void testSignFailureOnFirstFailureOnSecond() throws MojoExecutionException, JavaToolException + { + AbstractJarsignerMojo mojo = mock( AbstractJarsignerMojo.class ); + JarSigner jarSigner = mock( JarSigner.class ); + JarSignerRequest request = mock( JarSignerRequest.class ); + doCallRealMethod().when( mojo ).sign( jarSigner, request, 2 ); + JavaToolResult result1 = new JavaToolResult(); + result1.setExitCode( 1 ); + JavaToolResult result2 = new JavaToolResult(); + result2.setExitCode( 1 ); + when( jarSigner.execute( request ) ) + .thenReturn( result1 ) + .thenReturn( result2 ); + + mojo.sign( jarSigner, request, 2 ); + } +}