diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 0f17e8fdb4..2043632f18 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -2,6 +2,11 @@ ## 2.5 (NOT YET RELEASED) + * [Fixed Issue 187][issue-187] + + create target directory when run dependency update report. + Thanks to Ilja Dubinin. + * [Pull Request #189][pull-189] Fixed inccorect links. Thanks to Anton Johansson. @@ -68,4 +73,5 @@ [issue-167]: https://github.com/mojohaus/versions-maven-plugin/issues/167 [issue-168]: https://github.com/mojohaus/versions-maven-plugin/issues/168 [issue-177]: https://github.com/mojohaus/versions-maven-plugin/issues/177 +[issue-187]: https://github.com/mojohaus/versions-maven-plugin/issues/187 [pull-189]: https://github.com/mojohaus/versions-maven-plugin/pull/189 diff --git a/src/it/it-rules-via-classpath-001/invoker.properties b/src/it/it-rules-via-classpath-001/invoker.properties new file mode 100644 index 0000000000..681243c8ef --- /dev/null +++ b/src/it/it-rules-via-classpath-001/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-latest-releases +invoker.buildResult = failure diff --git a/src/it/it-rules-via-classpath-001/pom.xml b/src/it/it-rules-via-classpath-001/pom.xml new file mode 100644 index 0000000000..6a52cfba4a --- /dev/null +++ b/src/it/it-rules-via-classpath-001/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + + localhost + it-rules-via-classpath-001 + 1.0 + pom + GH-193: Fail if resource is not found + + + + localhost + version-rules + 3.0.1 + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + classpath:///package/foo/bar/rule-set.xml + + + + + + diff --git a/src/it/it-rules-via-classpath-001/verify.bsh b/src/it/it-rules-via-classpath-001/verify.bsh new file mode 100644 index 0000000000..e79df00228 --- /dev/null +++ b/src/it/it-rules-via-classpath-001/verify.bsh @@ -0,0 +1,22 @@ +import java.io.*; +import org.codehaus.plexus.util.FileUtils; + +try +{ + File file = new File( basedir, "build.log" ); + String buf = FileUtils.fileRead( file, "UTF-8" ); + String expectedMessage = "Resource \"classpath:///package/foo/bar/rule-set.xml\" not found in classpath."; + + if ( buf.indexOf( expectedMessage ) < 0 ) + { + System.err.println( "Build should have failed as the requested resource is not present." ); + return false; + } +} +catch( Throwable t ) +{ + t.printStackTrace(); + return false; +} + +return true; diff --git a/src/it/it-rules-via-classpath-002/invoker.properties b/src/it/it-rules-via-classpath-002/invoker.properties new file mode 100644 index 0000000000..8d6b718473 --- /dev/null +++ b/src/it/it-rules-via-classpath-002/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=clean install ${project.groupId}:${project.artifactId}:${project.version}:use-latest-releases +invoker.buildResult = success diff --git a/src/it/it-rules-via-classpath-002/pom.xml b/src/it/it-rules-via-classpath-002/pom.xml new file mode 100644 index 0000000000..c4177f37c4 --- /dev/null +++ b/src/it/it-rules-via-classpath-002/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + + localhost + it-rules-via-classpath-002 + 1.0 + pom + GH-193: Succeed if resource is found + + + + localhost + version-rules + 3.0.1 + + + localhost + setup-provide-rules-in-jar + 1.0 + + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + classpath:///package/foo/bar/rules.xml + + + + localhost + setup-provide-rules-in-jar + 1.0 + + + + + + + + diff --git a/src/it/it-rules-via-classpath-002/verify.bsh b/src/it/it-rules-via-classpath-002/verify.bsh new file mode 100644 index 0000000000..23c386d10d --- /dev/null +++ b/src/it/it-rules-via-classpath-002/verify.bsh @@ -0,0 +1,22 @@ +import java.io.*; +import org.codehaus.plexus.util.FileUtils; + +try +{ + File file = new File( basedir, "build.log" ); + String buf = FileUtils.fileRead( file, "UTF-8" ); + String expectedMessage = "Resource \"classpath:///package/foo/bar/rules.xml\" not found in classpath."; + + if ( buf.indexOf( expectedMessage ) >= 0 ) + { + System.err.println( "File resource rules.xml should have been found in the classpath." ); + return false; + } +} +catch( Throwable t ) +{ + t.printStackTrace(); + return false; +} + +return true; diff --git a/src/it/it-rules-via-classpath-003/invoker.properties b/src/it/it-rules-via-classpath-003/invoker.properties new file mode 100644 index 0000000000..8d6b718473 --- /dev/null +++ b/src/it/it-rules-via-classpath-003/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=clean install ${project.groupId}:${project.artifactId}:${project.version}:use-latest-releases +invoker.buildResult = success diff --git a/src/it/it-rules-via-classpath-003/pom.xml b/src/it/it-rules-via-classpath-003/pom.xml new file mode 100644 index 0000000000..54eadccdbd --- /dev/null +++ b/src/it/it-rules-via-classpath-003/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + localhost + it-rules-via-classpath-003 + 1.0 + pom + GH-193: Found rules file is used by the plugin + + + + localhost + version-rules + 3.0.1 + + + localhost + setup-provide-rules-in-jar + 1.0 + + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + classpath:///package/foo/bar/rules.xml + + + + localhost + setup-provide-rules-in-jar + 1.0 + + + + + + + diff --git a/src/it/it-rules-via-classpath-003/verify.bsh b/src/it/it-rules-via-classpath-003/verify.bsh new file mode 100644 index 0000000000..470b14115e --- /dev/null +++ b/src/it/it-rules-via-classpath-003/verify.bsh @@ -0,0 +1,21 @@ +import java.io.*; +import org.codehaus.plexus.util.FileUtils; + +try +{ + File file = new File( basedir, "pom.xml" ); + String buf = FileUtils.fileRead( file, "UTF-8" ); + + if ( buf.indexOf( "3.0.1-1.1" ) < 0 ) + { + System.err.println( "Version of version-rules not bumped to 3.0.1-1.1" ); + return false; + } +} +catch( Throwable t ) +{ + t.printStackTrace(); + return false; +} + +return true; diff --git a/src/it/setup-provide-rules-in-jar/invoker.properties b/src/it/setup-provide-rules-in-jar/invoker.properties new file mode 100644 index 0000000000..4b89532743 --- /dev/null +++ b/src/it/setup-provide-rules-in-jar/invoker.properties @@ -0,0 +1 @@ +invoker.goals=clean install diff --git a/src/it/setup-provide-rules-in-jar/pom.xml b/src/it/setup-provide-rules-in-jar/pom.xml new file mode 100644 index 0000000000..5c35f8f61e --- /dev/null +++ b/src/it/setup-provide-rules-in-jar/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + + localhost + setup-provide-rules-in-jar + 1.0 + jar + GH-193: Provide a rules file within a jar + + + diff --git a/src/it/setup-provide-rules-in-jar/src/main/resources/package/foo/bar/rules.xml b/src/it/setup-provide-rules-in-jar/src/main/resources/package/foo/bar/rules.xml new file mode 100644 index 0000000000..3e7699c7fe --- /dev/null +++ b/src/it/setup-provide-rules-in-jar/src/main/resources/package/foo/bar/rules.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java index 7ba3fa7753..7841d9f6ba 100644 --- a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java +++ b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsReport.java @@ -160,7 +160,9 @@ public abstract class AbstractVersionsReport private String serverId; /** - * The Wagon URI of a ruleSet file containing the rules that control how to compare version numbers. + * URI of a ruleSet file containing the rules that control how to compare + * version numbers. The URI could be either a Wagon URI or a classpath URI + * (e.g. classpath:///package/sub/package/rules.xml). * * @since 1.0-alpha-3 */ diff --git a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java index 2483188c7b..f5b3c65ce1 100644 --- a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java +++ b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java @@ -148,7 +148,9 @@ public abstract class AbstractVersionsUpdaterMojo private String serverId; /** - * The Wagon URI of a ruleSet file containing the rules that control how to compare version numbers. + * URI of a ruleSet file containing the rules that control how to compare + * version numbers. The URI could be either a Wagon URI or a classpath URI + * (e.g. classpath:///package/sub/package/rules.xml). * * @since 1.0-alpha-3 */ diff --git a/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java b/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java index f6f80120fe..7459113f6e 100644 --- a/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java +++ b/src/main/java/org/codehaus/mojo/versions/api/DefaultVersionsHelper.java @@ -66,10 +66,8 @@ import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.*; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -99,6 +97,8 @@ public class DefaultVersionsHelper implements VersionsHelper { + private static final String CLASSPATH_PROTOCOL = "classpath"; + private static final String TYPE_EXACT = "exact"; private static final String TYPE_REGEX = "regex"; @@ -222,38 +222,16 @@ private static RuleSet getRuleSet( Wagon wagon, String remoteURI ) try { wagon.get( remoteURI, tempFile ); - RuleXpp3Reader reader = new RuleXpp3Reader(); - FileInputStream fis = new FileInputStream( tempFile ); + InputStream is = new FileInputStream(tempFile ); try { - BufferedInputStream bis = new BufferedInputStream( fis ); - try - { - return reader.read( bis ); - } - catch ( XmlPullParserException e ) - { - final IOException ioe = new IOException(); - ioe.initCause( e ); - throw ioe; - } - finally - { - try - { - bis.close(); - } - catch ( IOException e ) - { - // ignore - } - } + return readRulesFromStream(is); } finally { try { - fis.close(); + is.close(); } catch ( IOException e ) { @@ -271,6 +249,34 @@ private static RuleSet getRuleSet( Wagon wagon, String remoteURI ) } } + private static RuleSet readRulesFromStream(InputStream stream) + throws IOException { + RuleXpp3Reader reader = new RuleXpp3Reader(); + BufferedInputStream bis = new BufferedInputStream( stream ); + + try + { + return reader.read( bis ); + } + catch ( XmlPullParserException e ) + { + final IOException ioe = new IOException(); + ioe.initCause( e ); + throw ioe; + } + finally + { + try + { + bis.close(); + } + catch ( IOException e ) + { + // ignore + } + } + } + static boolean exactMatch( String wildcardRule, String value ) { Pattern p = Pattern.compile( RegexUtils.convertWildcardsToRegex( wildcardRule, true ) ); @@ -285,86 +291,118 @@ static boolean match( String wildcardRule, String value ) private static RuleSet loadRuleSet( String serverId, Settings settings, WagonManager wagonManager, String rulesUri, Log logger ) - throws MojoExecutionException - { + throws MojoExecutionException { RuleSet ruleSet = new RuleSet(); - if ( rulesUri != null && rulesUri.trim().length() != 0 ) - { - try - { - int split = rulesUri.lastIndexOf( '/' ); - String baseUri; - String fileUri; - if ( split != -1 ) - { - baseUri = rulesUri.substring( 0, split ) + '/'; - fileUri = split + 1 < rulesUri.length() ? rulesUri.substring( split + 1 ) : ""; - } - else - { - baseUri = rulesUri; - fileUri = ""; - } - try - { - Wagon wagon = WagonUtils.createWagon( serverId, baseUri, wagonManager, settings, logger ); - try - { - logger.debug( "Trying to load ruleset from file \"" + fileUri + "\" in " + baseUri ); - final RuleSet loaded = getRuleSet( wagon, fileUri ); - ruleSet.setRules( loaded.getRules() ); - ruleSet.setIgnoreVersions( loaded.getIgnoreVersions() ); - logger.debug( "Rule set loaded" ); - } - finally - { - if ( wagon != null ) - { - try - { - wagon.disconnect(); - } - catch ( ConnectionException e ) - { - logger.warn( "Could not disconnect wagon!", e ); - } - } + boolean rulesUriGiven = isRulesUriNotBlank(rulesUri); + + if (rulesUriGiven) { + RuleSet loadedRules; + if (isClasspathUri(rulesUri)) { + loadedRules = getRulesFromClasspath(rulesUri, logger); + } else { + loadedRules = getRulesViaWagon(rulesUri, logger, serverId, serverId, wagonManager, + settings); + } + + ruleSet.setIgnoreVersions(loadedRules.getIgnoreVersions()); + ruleSet.setRules(loadedRules.getRules()); + } + + return ruleSet; + } + + private static RuleSet getRulesFromClasspath(String uri, Log logger) + throws MojoExecutionException { + logger.debug("Going to load rules from \"" + uri + "\""); + + String choppedUrl = uri.substring(CLASSPATH_PROTOCOL.length() + 3); + + URL url = DefaultVersionsHelper.class.getResource(choppedUrl); + + if (null == url) { + String message = "Resource \"" + uri + "\" not found in classpath."; + + throw new MojoExecutionException(message); + } + + try { + RuleSet rules = readRulesFromStream(url.openStream()); + logger.debug("Loaded rules from \"" + uri + "\" successfully"); + return rules; + } + catch (IOException e) { + throw new MojoExecutionException("Could not load specified rules from " + uri, e); + } + } + + private static boolean isRulesUriNotBlank(String rulesUri) { + return rulesUri != null && rulesUri.trim().length() != 0; + } + + private static RuleSet getRulesViaWagon(String rulesUri, Log logger, String serverId, String id, + WagonManager wagonManager, Settings settings) + throws MojoExecutionException { + RuleSet loadedRules = new RuleSet(); + + int split = rulesUri.lastIndexOf('/'); + String baseUri = rulesUri; + String fileUri = ""; + + if (split != -1) { + baseUri = rulesUri.substring(0, split) + '/'; + fileUri = split + 1 < rulesUri.length() ? rulesUri.substring(split + 1) : ""; + } + + try { + Wagon wagon = WagonUtils.createWagon(serverId, baseUri, wagonManager, settings, logger); + try { + logger.debug("Trying to load ruleset from file \"" + fileUri + "\" in " + baseUri); + loadedRules = getRuleSet(wagon, fileUri); + } + finally { + logger.debug("Rule set loaded"); + + if (wagon != null) { + try { + wagon.disconnect(); + } + catch (ConnectionException e) { + logger.warn("Could not disconnect wagon!", e); } } - catch ( TransferFailedException e ) - { - throw new MojoExecutionException( "Could not transfer rules from " + rulesUri, e ); - } - catch ( AuthorizationException e ) - { - throw new MojoExecutionException( "Authorization failure trying to load rules from " + rulesUri, - e ); - } - catch ( ResourceDoesNotExistException e ) - { - throw new MojoExecutionException( "Could not load specified rules from " + rulesUri, e ); - } - catch ( AuthenticationException e ) - { - throw new MojoExecutionException( "Authentication failure trying to load rules from " + rulesUri, - e ); - } - catch ( UnsupportedProtocolException e ) - { - throw new MojoExecutionException( "Unsupported protocol for " + rulesUri, e ); - } - catch ( ConnectionException e ) - { - throw new MojoExecutionException( "Could not establish connection to " + rulesUri, e ); - } - } - catch ( IOException e ) - { - throw new MojoExecutionException( "Could not load specified rules from " + rulesUri, e ); } } - return ruleSet; + catch (TransferFailedException e) { + throw new MojoExecutionException("Could not transfer rules from " + rulesUri, e); + } + catch (AuthorizationException e) { + throw new MojoExecutionException("Authorization failure trying to load rules from " + rulesUri, e); + } + catch (ResourceDoesNotExistException e) { + throw new MojoExecutionException("Could not load specified rules from " + rulesUri, e); + } + catch (AuthenticationException e) { + throw new MojoExecutionException("Authentication failure trying to load rules from " + rulesUri, e); + } + catch (UnsupportedProtocolException e) { + throw new MojoExecutionException("Unsupported protocol for " + rulesUri, e); + } + catch (ConnectionException e) { + throw new MojoExecutionException("Could not establish connection to " + rulesUri, e); + } + catch (IOException e) { + throw new MojoExecutionException("Could not load specified rules from " + rulesUri, e); + } + + return loadedRules; + } + + static boolean isClasspathUri(String uri) { + boolean startsWithProtocol = null != uri && uri.startsWith(CLASSPATH_PROTOCOL); + boolean hasColonNext = null != uri && uri.charAt(CLASSPATH_PROTOCOL.length()) == ':'; + + return startsWithProtocol && hasColonNext; } /** diff --git a/src/site/apt/version-rules.apt.vm b/src/site/apt/version-rules.apt.vm index bbb6a06b9d..d098749e06 100644 --- a/src/site/apt/version-rules.apt.vm +++ b/src/site/apt/version-rules.apt.vm @@ -134,3 +134,40 @@ Version number rules ... --- + + You can provide your ruleset xml file also within a jar, if you want to distribute + your ruleset xml as Maven artifact. Therefore you have to declare the containing + jar as direct dependency of the <> and to use classpath + as protocol. + +--- + + ... + + ... + + ... + + org.codehaus.mojo + versions-maven-plugin + ${pluginVersion} + + ... + classpath:///package/foo/bar/rules.xml + ... + + + + com.mycompany + version-rules + 1.0 + + + + ... + + ... + + ... + +--- \ No newline at end of file diff --git a/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java b/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java index 0b03df3d01..a8dc413d9c 100644 --- a/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java +++ b/src/test/java/org/codehaus/mojo/versions/api/DefaultVersionsHelperTest.java @@ -45,6 +45,7 @@ import org.apache.maven.execution.MavenSession; import org.codehaus.mojo.versions.Property; import org.codehaus.mojo.versions.ordering.VersionComparators; +import org.hamcrest.CoreMatchers; import java.util.ArrayList; import java.util.List; @@ -175,22 +176,36 @@ public void testMVERSIONS159_ExcludedAndNotIncluded() assertTrue( result.isEmpty() ); } + public void testIsClasspathUriDetectsClassPathProtocol() throws MojoExecutionException { + DefaultVersionsHelper helper = createHelper(); + String uri = "classpath:/p/a/c/k/a/g/e/resource.res"; - private VersionsHelper createHelper() + assertThat(DefaultVersionsHelper.isClasspathUri(uri), CoreMatchers.is(true)); + } + + public void testIsClasspathUriDetectsThatItIsDifferentProtocol() throws MojoExecutionException { + DefaultVersionsHelper helper = createHelper(); + String uri = "http://10.10.10.10/p/a/c/k/a/g/e/resource.res"; + + assertThat(DefaultVersionsHelper.isClasspathUri(uri), CoreMatchers.is(false)); + } + + + private DefaultVersionsHelper createHelper() throws MojoExecutionException { return createHelper( new MavenMetadataSource() ); } - private VersionsHelper createHelper( ArtifactMetadataSource metadataSource ) throws MojoExecutionException + private DefaultVersionsHelper createHelper( ArtifactMetadataSource metadataSource ) throws MojoExecutionException { final String resourcePath = "/" + getClass().getPackage().getName().replace( '.', '/' ) + "/rules.xml"; final String rulesUri = getClass().getResource( resourcePath ).toExternalForm(); - VersionsHelper helper = createHelper( rulesUri, metadataSource ); + DefaultVersionsHelper helper = createHelper( rulesUri, metadataSource ); return helper; } - private VersionsHelper createHelper( String rulesUri, ArtifactMetadataSource metadataSource ) + private DefaultVersionsHelper createHelper( String rulesUri, ArtifactMetadataSource metadataSource ) throws MojoExecutionException { final DefaultWagonManager wagonManager = new DefaultWagonManager() @@ -202,7 +217,7 @@ public Wagon getWagon( Repository repository ) } }; - VersionsHelper helper = + DefaultVersionsHelper helper = new DefaultVersionsHelper( new DefaultArtifactFactory(), new DefaultArtifactResolver(), metadataSource, new ArrayList(), new ArrayList(), new DefaultArtifactRepository( "", "", new DefaultRepositoryLayout() ),