diff --git a/src/main/java/com/jayway/maven/plugins/android/configuration/ManifestMerger.java b/src/main/java/com/jayway/maven/plugins/android/configuration/ManifestMerger.java index 4380481b3..adb5e5bf7 100644 --- a/src/main/java/com/jayway/maven/plugins/android/configuration/ManifestMerger.java +++ b/src/main/java/com/jayway/maven/plugins/android/configuration/ManifestMerger.java @@ -33,6 +33,12 @@ public class ManifestMerger */ protected Boolean versionCodeUpdateFromVersion; + /** + * Mirror of {@link com.jayway.maven.plugins.android.standalonemojos.ManifestMergerMojo + * #manifestVersionNamingPattern}. + */ + protected String versionNamingPattern; + /** * Mirror of {@link com.jayway.maven.plugins.android.standalonemojos.ManifestMergerMojo * #manifestVersionDigits}. @@ -71,6 +77,11 @@ public Boolean getVersionCodeUpdateFromVersion() return versionCodeUpdateFromVersion; } + public String getVersionNamingPattern() + { + return versionNamingPattern; + } + public String getVersionDigits() { return versionDigits; diff --git a/src/main/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParser.java b/src/main/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParser.java new file mode 100644 index 000000000..79e3f132c --- /dev/null +++ b/src/main/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParser.java @@ -0,0 +1,56 @@ +package com.jayway.maven.plugins.android.configuration; + +import static java.lang.String.format; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.maven.plugin.MojoExecutionException; + +/** + * Regex-based VersionElementParser implementation. + * + * @author Wang Xuerui + * + */ +public class RegexVersionElementParser implements VersionElementParser +{ + + private Pattern namingPattern; + + public RegexVersionElementParser( String pattern ) + { + namingPattern = Pattern.compile( pattern ); + } + + @Override + public int[] parseVersionElements( final String versionName ) throws MojoExecutionException + { + final Matcher matcher = namingPattern.matcher( versionName ); + if ( ! matcher.find() ) + { + throw new MojoExecutionException( format( + "The version naming pattern failed to match version name: %s against %s", + namingPattern, versionName ) ); + } + + int elementCount = matcher.groupCount(); + int[] result = new int[elementCount]; + + for ( int i = 0; i < elementCount; i++ ) + { + // Capturing groups start at index 1 + try + { + result[i] = Integer.valueOf( matcher.group( i + 1 ) ); + } + catch ( NumberFormatException ignored ) + { + // Either the group is not present, or cannot be cast to integer. + result[i] = 0; + } + } + + return result; + } +} diff --git a/src/main/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParser.java b/src/main/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParser.java new file mode 100644 index 000000000..d7a1c8b78 --- /dev/null +++ b/src/main/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParser.java @@ -0,0 +1,27 @@ +package com.jayway.maven.plugins.android.configuration; + +import org.apache.maven.plugin.MojoExecutionException; + +/** + * VersionElementParser implementing the old version generator behavior. + * + * @author Wang Xuerui + * + */ +public class SimpleVersionElementParser implements VersionElementParser +{ + + @Override + public int[] parseVersionElements( final String versionName ) throws MojoExecutionException + { + final String[] versionNameElements = versionName.replaceAll( "[^0-9.]", "" ).split( "\\." ); + int[] result = new int[versionNameElements.length]; + + for ( int i = 0; i < versionNameElements.length; i++ ) + { + result[i] = Integer.valueOf( versionNameElements[i] ); + } + + return result; + } +} diff --git a/src/main/java/com/jayway/maven/plugins/android/configuration/VersionElementParser.java b/src/main/java/com/jayway/maven/plugins/android/configuration/VersionElementParser.java new file mode 100644 index 000000000..60494f9b4 --- /dev/null +++ b/src/main/java/com/jayway/maven/plugins/android/configuration/VersionElementParser.java @@ -0,0 +1,14 @@ +package com.jayway.maven.plugins.android.configuration; + +import org.apache.maven.plugin.MojoExecutionException; + +/** + * Interface for parsing version names into version elements. + * + * @author Wang Xuerui + * + */ +public interface VersionElementParser +{ + int[] parseVersionElements( final String versionName ) throws MojoExecutionException; +} diff --git a/src/main/java/com/jayway/maven/plugins/android/configuration/VersionGenerator.java b/src/main/java/com/jayway/maven/plugins/android/configuration/VersionGenerator.java index 1fadd2e4b..afc718d9e 100644 --- a/src/main/java/com/jayway/maven/plugins/android/configuration/VersionGenerator.java +++ b/src/main/java/com/jayway/maven/plugins/android/configuration/VersionGenerator.java @@ -7,6 +7,7 @@ /** * @author Pappy STÄ‚NESCU <pappy.stanescu@gmail.com> + * @author Wang Xuerui */ public class VersionGenerator { @@ -15,12 +16,19 @@ public class VersionGenerator private final int[] multipliers; + private final VersionElementParser elementParser; + public VersionGenerator() { - this( "4,3,3" ); + this( "4,3,3", "" ); } public VersionGenerator( String versionDigits ) + { + this( versionDigits, "" ); + } + + public VersionGenerator( String versionDigits, String versionNamingPattern ) { final String[] digits = versionDigits.split( "[,;]" ); @@ -42,11 +50,22 @@ public VersionGenerator( String versionDigits ) { throw new IllegalArgumentException( format( "Invalid number of digits, got %d", total ) ); } + + // Choose a version element parser implementation based on the naming pattern + // passed in; an empty pattern triggers the old behavior. + if ( ! versionNamingPattern.isEmpty() ) + { + this.elementParser = new RegexVersionElementParser( versionNamingPattern ); + } + else + { + this.elementParser = new SimpleVersionElementParser(); + } } public int generate( String versionName ) throws MojoExecutionException { - final String[] versionNameElements = versionName.replaceAll( "[^0-9.]", "" ).split( "\\." ); + final int[] versionElements = elementParser.parseVersionElements( versionName ); long versionCode = 0; @@ -54,10 +73,9 @@ public int generate( String versionName ) throws MojoExecutionException { versionCode *= this.multipliers[k]; - if ( k < versionNameElements.length ) + if ( k < versionElements.length ) { - final String versionElement = versionNameElements[k]; - final int elementValue = Integer.valueOf( versionElement ); + final int elementValue = versionElements[k]; if ( elementValue >= this.multipliers[k] ) { diff --git a/src/main/java/com/jayway/maven/plugins/android/standalonemojos/ManifestMergerMojo.java b/src/main/java/com/jayway/maven/plugins/android/standalonemojos/ManifestMergerMojo.java index 4e2c228ad..6be84747a 100644 --- a/src/main/java/com/jayway/maven/plugins/android/standalonemojos/ManifestMergerMojo.java +++ b/src/main/java/com/jayway/maven/plugins/android/standalonemojos/ManifestMergerMojo.java @@ -61,6 +61,7 @@ public class ManifestMergerMojo extends AbstractAndroidMojo * <versionName></versionName> * <versionCode>123</versionCode> * <versionCodeUpdateFromVersion>true|false</versionCodeUpdateFromVersion> + * <versionNamingPattern></versionNamingPattern> * <mergeLibraries>true|false</mergeLibraries> * <mergeReportFile>${project.build.directory}/ManifestMergeReport.txt</mergeReportFile> * <usesSdk> @@ -112,6 +113,20 @@ public class ManifestMergerMojo extends AbstractAndroidMojo @Parameter( property = "android.manifest.versionCodeUpdateFromVersion", defaultValue = "false" ) protected Boolean manifestVersionCodeUpdateFromVersion = false; + /** + * Optionally use a pattern to match version elements for automatic generation of version codes, + * useful in case of complex version naming schemes. The new behavior is disabled by default; + * set the pattern to a non-empty string to activate. Otherwise, continue using the old + * behavior of separating version elements by dots and ignoring all non-digit characters. + * The pattern is standard Java regex. Capturing groups in the pattern are sequentially passed + * to the version code generator, while other parts are ignored. Be sure to properly escape + * your pattern string, in case you use characters that have special meaning in XML. + * Exposed via the project property + * android.manifestMerger.versionNamingPattern. + */ + @Parameter( property = "android.manifestMerger.versionNamingPattern", defaultValue = "" ) + protected String manifestVersionNamingPattern; + /** * The number of digits per version element. Must be specified as a comma/semicolon separated list of * digits, one for each version element, Exposed via the project property @@ -140,6 +155,7 @@ public class ManifestMergerMojo extends AbstractAndroidMojo */ protected UsesSdk manifestUsesSdk; private Boolean parsedVersionCodeUpdateFromVersion; + private String parsedVersionNamingPattern; private String parsedVersionDigits; private Boolean parsedMergeLibraries; private String parsedVersionName; @@ -172,6 +188,7 @@ public void execute() throws MojoExecutionException, MojoFailureException getLog().debug( " versionCode=" + parsedVersionCode ); getLog().debug( " usesSdk=" + parsedUsesSdk ); getLog().debug( " versionCodeUpdateFromVersion=" + parsedVersionCodeUpdateFromVersion ); + getLog().debug( " versionNamingPattern=" + parsedVersionNamingPattern ); getLog().debug( " versionDigits=" + parsedVersionDigits ); getLog().debug( " mergeLibraries=" + parsedMergeLibraries ); getLog().debug( " mergeReportFile=" + parsedMergeReportFile ); @@ -214,6 +231,14 @@ private void parseConfiguration() { parsedVersionCodeUpdateFromVersion = manifestVersionCodeUpdateFromVersion; } + if ( manifestMerger.getVersionNamingPattern() != null ) + { + parsedVersionNamingPattern = manifestMerger.getVersionNamingPattern(); + } + else + { + parsedVersionNamingPattern = manifestVersionNamingPattern; + } if ( manifestMerger.getVersionDigits() != null ) { parsedVersionDigits = manifestMerger.getVersionDigits(); @@ -253,6 +278,7 @@ private void parseConfiguration() parsedVersionCode = manifestVersionCode; parsedUsesSdk = manifestUsesSdk; parsedVersionCodeUpdateFromVersion = manifestVersionCodeUpdateFromVersion; + parsedVersionNamingPattern = manifestVersionNamingPattern; parsedVersionDigits = manifestVersionDigits; parsedMergeLibraries = manifestMergeLibraries; parsedMergeReportFile = manifestMergeReportFile; @@ -275,8 +301,8 @@ public void manifestMergerV2() throws MojoExecutionException, MojoFailureExcepti } if ( parsedVersionCodeUpdateFromVersion ) { - VersionGenerator gen = new VersionGenerator( parsedVersionDigits ); - + VersionGenerator gen = new VersionGenerator( parsedVersionDigits, parsedVersionNamingPattern ); + versionCode = gen.generate( parsedVersionName ); } else diff --git a/src/test/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParserTest.java b/src/test/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParserTest.java new file mode 100644 index 000000000..ecce16a7e --- /dev/null +++ b/src/test/java/com/jayway/maven/plugins/android/configuration/RegexVersionElementParserTest.java @@ -0,0 +1,57 @@ +package com.jayway.maven.plugins.android.configuration; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.fail; + +import org.apache.maven.plugin.MojoExecutionException; +import org.junit.Test; + +/** + * @author Wang Xuerui + */ +public class RegexVersionElementParserTest +{ + + @Test + public void prefixMatch() throws MojoExecutionException + { + assertArrayEquals( new int[] { 4, 1, 16, 8 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)" ).parseVersionElements( "4.1.16.8-SNAPSHOT.1946" ) ); + assertArrayEquals( new int[] { 0, 0, 38 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)-(\\d+)" ).parseVersionElements( "0.0-38-g493f883" ) ); + assertArrayEquals( new int[] { 5, 0, 1 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+)" ).parseVersionElements( "5.0.1 (1642443)" ) ); + assertArrayEquals( new int[] { 6, 1, 0, 66 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)" ).parseVersionElements( "6.1.0.66-r1062275" ) ); + } + + @Test + public void fullMatch() throws MojoExecutionException + { + assertArrayEquals( new int[] { 5, 0, 1, 1642443 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+) \\((\\d+)\\)$" ).parseVersionElements( "5.0.1 (1642443)" ) ); + assertArrayEquals( new int[] { 6, 1, 0, 66, 1062275 }, new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)-r(\\d+)$" ).parseVersionElements( "6.1.0.66-r1062275" ) ); + } + + @Test + public void variableLengthResult() throws MojoExecutionException + { + final String pattern1 = "^(\\d+)\\.(\\d+)(?:-(\\d+)-g[0-9a-f]+(?:-dirty)?)?$"; + assertArrayEquals( new int[] { 0, 0, 38 }, new RegexVersionElementParser( pattern1 ).parseVersionElements( "0.0-38-g493f883" ) ); + assertArrayEquals( new int[] { 0, 0, 38 }, new RegexVersionElementParser( pattern1 ).parseVersionElements( "0.0-38-g493f883-dirty" ) ); + assertArrayEquals( new int[] { 1, 0, 0 }, new RegexVersionElementParser( pattern1 ).parseVersionElements( "1.0" ) ); + + final String pattern2 = "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)(?:-[A-Z]+\\.(\\d+))?$"; + assertArrayEquals( new int[] { 4, 1, 16, 8, 1946 }, new RegexVersionElementParser( pattern2 ).parseVersionElements( "4.1.16.8-SNAPSHOT.1946" ) ); + assertArrayEquals( new int[] { 4, 1, 16, 8, 0 }, new RegexVersionElementParser( pattern2 ).parseVersionElements( "4.1.16.8" ) ); + } + + @Test + public void failedMatch() throws MojoExecutionException + { + try + { + new RegexVersionElementParser( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)" ).parseVersionElements( "4.1.16-SNAPSHOT.1946" ); + fail( "Expecting MojoExecutionException" ); + } + catch ( MojoExecutionException e ) + { + System.err.println( "OK: " + e ); + } + } +} diff --git a/src/test/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParserTest.java b/src/test/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParserTest.java new file mode 100644 index 000000000..5a12e09c8 --- /dev/null +++ b/src/test/java/com/jayway/maven/plugins/android/configuration/SimpleVersionElementParserTest.java @@ -0,0 +1,29 @@ +package com.jayway.maven.plugins.android.configuration; + +import static org.junit.Assert.assertArrayEquals; + +import org.apache.maven.plugin.MojoExecutionException; +import org.junit.Test; + +/** + * @author Wang Xuerui + */ +public class SimpleVersionElementParserTest +{ + + @Test + public void simple() throws MojoExecutionException + { + assertArrayEquals( new int[] { 2, 14, 748, 3647 }, new SimpleVersionElementParser().parseVersionElements( "2.14.748.3647" ) ); + assertArrayEquals( new int[] { 2147, 483, 64, 7 }, new SimpleVersionElementParser().parseVersionElements( "2147.483.64.7" ) ); + assertArrayEquals( new int[] { 2, 1, 4, 7, 4, 8, 3, 6, 4, 7 }, new SimpleVersionElementParser().parseVersionElements( "2.1.4.7.4.8.3.6.4.7" ) ); + } + + @Test + public void mixed() throws MojoExecutionException + { + assertArrayEquals( new int[] { 4, 1, 16, 8, 1946 }, new SimpleVersionElementParser().parseVersionElements( "4.1.16.8-SNAPSHOT.1946" ) ); + assertArrayEquals( new int[] { 1, 2, 15, 8, 1946 }, new SimpleVersionElementParser().parseVersionElements( "1.2.15.8-SNAPSHOT.1946" ) ); + assertArrayEquals( new int[] { 2, 1, 6, 1246 }, new SimpleVersionElementParser().parseVersionElements( "2.1.6-SNAPSHOT.1246" ) ); + } +} diff --git a/src/test/java/com/jayway/maven/plugins/android/configuration/VersionGeneratorTest.java b/src/test/java/com/jayway/maven/plugins/android/configuration/VersionGeneratorTest.java index 43d529a35..d71ff626e 100644 --- a/src/test/java/com/jayway/maven/plugins/android/configuration/VersionGeneratorTest.java +++ b/src/test/java/com/jayway/maven/plugins/android/configuration/VersionGeneratorTest.java @@ -25,10 +25,17 @@ public void generate() throws MojoExecutionException assertEquals( 2147483647, new VersionGenerator( "1,1,1,1,1,1,1,1,1,1" ).generate( "2.1.4.7.4.8.3.6.4.7" ) ); } + @Test + public void generateRegex() throws MojoExecutionException + { + assertEquals( 2147483647, new VersionGenerator( "1,2,3,4", "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" ).generate( "2.14.748.3647" ) ); + assertEquals( 2147483647, new VersionGenerator( "4,3,2,1", "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" ).generate( "2147.483.64.7" ) ); + } + @Test public void compare() throws MojoExecutionException { VersionGenerator gen = new VersionGenerator( "3,3,3" ); - + assertTrue( gen.generate( "1.0" ) < gen.generate( "1.0.1" ) ); assertTrue( gen.generate( "2.0" ) > gen.generate( "1.0.1" ) ); } @@ -37,10 +44,10 @@ public void compare() throws MojoExecutionException { public void realCase() throws MojoExecutionException { VersionGenerator gen = new VersionGenerator( "1,1,2,1,4" ); - + int v1 = gen.generate( "4.1.16.8-SNAPSHOT.1946" ); int v2 = gen.generate( "4.1.17.8-SNAPSHOT.1246" ); - + assertEquals(411681946, v1 ); assertEquals(411781246, v2 ); @@ -48,15 +55,55 @@ public void realCase() throws MojoExecutionException } + @Test + public void realCaseRegex() throws MojoExecutionException + { + { + VersionGenerator gen = new VersionGenerator( "1,1,2,1,4", "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)(?:-[A-Z]+\\.(\\d+))?$" ); + + int v1 = gen.generate( "4.1.16.8-SNAPSHOT.1946" ); + int v2 = gen.generate( "4.1.17.8" ); + + assertEquals( 411681946, v1 ); + assertEquals( 411780000, v2 ); + + assertTrue( v1 < v2 ); + } + + { + VersionGenerator gen = new VersionGenerator( "4,3,3", "^(\\d+)\\.(\\d+)(?:-(\\d+)-g[0-9a-f]+(?:-dirty)?)?$" ); + + int v1 = gen.generate( "0.0-38-g493f883" ); + int v2 = gen.generate( "0.1" ); + + assertEquals( 38, v1 ); + assertEquals( 1000, v2 ); + + assertTrue( v1 < v2 ); + } + + { + VersionGenerator gen = new VersionGenerator( "3,2,2,3", "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)" ); + + int v1 = gen.generate( "6.1.0.66-r1062275" ); + int v2 = gen.generate( "6.2.0.0-r1234567" ); + + assertEquals( 60100066, v1 ); + assertEquals( 60200000, v2 ); + + assertTrue( v1 < v2 ); + } + } + @Test public void mixedCase() throws MojoExecutionException { VersionGenerator g1 = new VersionGenerator( "1,1,2,1,4" ); VersionGenerator g2 = new VersionGenerator( "1,1,2,5" ); - + int v1 = g1.generate( "1.2.15.8-SNAPSHOT.1946" ); int v2 = g2.generate( "2.1.6-SNAPSHOT.1246" ); - + assertEquals(121581946, v1 ); assertEquals(210601246, v2 );