Maven error: URI has an authority component - maven

I'm pretty new to maven and trying to build a code on Windows that works fine in linux.
I have 2 local repositories in my pom.xml:
<repositories>
<repository>
<id>p2-repo-equinox_3.8.1</id>
<layout>p2</layout>
<url>file:///${basedir}/../xyz/abc/repository/</url>
</repository>
<repository>
<id>p2-repo-common</id>
<layout>p2</layout>
<url>file:///${basedir}/../xyz/def/repository/</url>
</repository>
</repositories>
When building, I get the error:
Internal error: java.lang.RuntimeException: Failed to load p2 repository with ID 'p2-repo-equinox_3.8.1' from location file://D:/maven/myproject/../xyz/abc/repository/: URI has an authority component -> [Help 1]
I found this post, and tried adding a third slash to pass an empty authority component ( file:///) which made it work, but I'm not sure why the issue only happens in Windows in the first place and not on Linux.
Any Advice appreciated.

The reason this doesn't cause an error on linux is probably due to the difference in the value of ${basedir} on the two platforms:
On Windows ${basedir} will be set to something like "c:/file/path"
file://c:/file/path <--- not happy
On linux ${basedir} will be like "/file/path"
file:///file/path <--- happy

On a windows machine, the complete syntax is file://host/path .
If the host is your machine(localhost), it can be omitted, resulting in file:///path .
See RFC 1738 – Uniform Resource Locators (URL)
A file URL takes the form:
file://<host>/<path>
[…]
As a special case, <host> can be the string "localhost" or the empty string; this is interpreted as 'the machine from which the URL is being interpreted'.

Related

How to provide my "rules.xml" file in -DrulesUri argument of maven versions:update-properties without needing to specify it in pom.xml file?

I am using Maven Versions plugin's update-properties goal to update properties in pom.xml of multiples projects. (https://www.mojohaus.org/versions-maven-plugin/update-properties-mojo.html). I want the latest version of the dependency for properties.
Now, there are some binaries with wrong versions. I want my code to ignore these versions. For this, I have created my "rules.xml" file. I want to provide it as -DrulesUri argument to update-properties goal.
I already tried specifying this rules.xml file in pom.xml file of project as shown on (Maven versions plugin: reference a rule.xml from a maven dependency?). This worked as the plugin could successfully ignore specified versions in rules.xml. So, there is no problem with rules.xml file. But, this is not useful in my case, since there are many projects involved and I cannot update pom.xml of each project.
The documentation of rulesUri property says "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)." This much documentation is not helping me. I would want an example on how to specify the rules.xml file in -DrulesUri argument. I tried specifying the rules.xml file as local relative path / absolute path. But, update-properties goal does not seem to recognize the rules and just proceeds similar to execution without -DrulesUri argument. I tried reading https://maven.apache.org/wagon/ to understand Wagon URIs. But, I did not find a simple way to upload my rules.xml somewhere and then use this Wagon URI to specify in -DrulesUri.
This is my rules.xml file :-
<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" comparisonMethod="maven" xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">25243.*.*</ignoreVersion>
</ignoreVersions>
<rules>
</rules>
</ruleset>
Use -Dmaven.version.rules
Example:
mvn versions:display-dependency-updates -Dmaven.version.rules=file:///$HOME/.m2/rules.xml
From AbstractVersionsReport.java source code:
/**
* 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. <code>classpath:///package/sub/package/rules.xml</code>).
*
* #since 1.0-alpha-3
*/
#Parameter( property = "maven.version.rules" )
private String rulesUri;

The target deployment path '...' does not match the POM's expected path prefix

I am trying to upload a pom.xml file to a Maven repository hosted on an Artifactory server. The <project> section of the pom.xml looks like this:
<groupId>com.x.y.z</groupId>
<artifactId>common</artifactId>
<version>2.3.0-RELEASE</version>
<packaging>jar</packaging>
I am using the Artifactory plugin for Jenkins in a Pipeline script and here is the uploadSpec
{
"files": [
{
"pattern": "target/common-2.3.0-RELEASE.jar",
"target": "REPOSITORY/com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.jar"
},
{
"pattern": "pom.xml",
"target": "REPOSITORY/com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.pom"
}
]
}
When I now try to upload the artifact, I'm getting the following error message:
java.io.IOException: Failed to deploy file.
Status code: 409
Response message: Artifactory returned the following errors:
The target deployment path 'com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.pom'
does not match the POM's expected path prefix 'com/x/y/z/common/2.2.7'.
Please verify your POM content for correctness and make sure the source path is a valid Maven repository root path. Status code: 409
Before I upload the RELEASE, I upload a SNAPSHOT which (in this case) had the version 2.2.7-SNAPSHOT. After that I bump the version to 2.3.0, re-build the project with mvn clean install and then start another upload to Artifactory. Somehow Artifactory still seems to expect the "old" version, when I try to upload the new version.
Edit
When I upload the file with curl, everything works as expected:
curl -user:password-T pom.xml \
"http://DOMAIN/artifactory/REPOSITORY/com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.pom"
So it seems like this is related to the Jenkins Artifactory Plugin.
You upload your pom file to an incorrect location. You use
REPOSITORY/com/x/y/z/common-2.3.0-RELEASE.pom
as a path, when the path should be
REPOSITORY/com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.pom
Note version-named directory that is missing.
The good news are you don't even need to bother with it. When you use our Artifactory.newMavenBuild for Maven builds, we'll take care of the correct deployment. See the example.
Can you try the below code in pipeline script?
{
"pattern": "pom.xml",
"target": "REPOSITORY/com/x/y/z/common/2.3.0-RELEASE/common-2.3.0-RELEASE.pom"
}
or if it doesn't work you can utilize maven deploy in pipeline script using
def mvnHome = tool mvnName
sh "$mvnHome/bin/mvn deploy -deploy-file -Durl=file:///C:/m2-repo \
-DrepositoryId=some.id \
-Dfile=path-to-your-artifact-jar \
-DpomFile=path-to-your-pom.xml

Maven Release Plugin - tagBase is ignored

I'm trying to create a release with the Maven Release Plugin, and it seems as if the tagBase setting is being completely ignored.
Here's what my pom looks like:
...
<scm>
<developerConnection>scm:svn:http://svn.server/svn/repos/.../project/trunk</developerConnection>
</scm>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<tagBase>http://svn.server/svn/repos/.../project/branches</tagBase>
</configuration>
</plugin>
</plugins>
</build>
...
And here's the mvn release command I'm running:
mvn release:prepare
I initially tried this with the -DdryRun=true option, and noticed that the pom.xml.tag file that got generated by the dry run was referencing the .../project/tags/ directory instead of the .../projects/branches/ directory specified in the tagBase. I tried this without the dry run, and the results were the same. The release was created in the tags directory in my SVN repository instead of in the branches directory per the tagBase setting in the pom.
Why is tagBase being ignored? How can I get the maven release plugin to create the release under .../project/branches/ instead of .../project/tags/?
Edit - Adding Some Additional Information:
I'm using version 2.5.3 of maven-release-plugin and Maven version 3.3.9.
After running the mvn release:prepare -DdryRun=true command, here's what the generated release.properties and pom.xml.tag files look like:
release.properties:
#release configuration
#Thu Aug 25 09:07:24 EDT 2016
scm.tagNameFormat=#{project.artifactId}-#{project.version}
scm.tag=project-1.0.0
project.scm.group.id\:project.tag=HEAD
pushChanges=true
scm.url=scm\:svn\:http\://svn.server/svn/repos/.../project/trunk
preparationGoals=clean verify
remoteTagging=true
projectVersionPolicyId=default
scm.commentPrefix=[maven-release-plugin]
scm.tagBase=http\://svn.server/svn/repos/.../project/branches
project.scm.group.id\:project.developerConnection=scm\:svn\:http\://svn.server/svn/repos/.../project/trunk
project.dev.group.id\:project=1.0.1-SNAPSHOT
project.rel.group.id\:project=1.0.0
exec.snapshotReleasePluginAllowed=false
exec.additionalArguments=-P my-active-profile
completedPhase=end-release
pom.xml.tag:
...
<scm>
<developerConnection>scm:svn:http://svn.server/svn/repos/.../project/tags/project-1.0.0</developerConnection>
</scm>
...
It looks like the scm.tagBase property is correct in the generated release.properties file, but the scm information in pom.xml.tag still references the tags directory instead of branches.
I started digging through the maven-release-plugin code and the maven-scm-provider-svn-commons code, and I'm pretty sure I've figured out why this is happening.
If the tagBase property matches the standard naming convention for the branches directory in an SVN repository (for example, http://svn.server/svn/repo/project/branches), then the tagBase gets ignored in favor of the standard tags directory. Here's the relevant code from version 1.9.4 of the maven-scm-provider-svn-commons project:
SvnTagBranchUtils.java:
public static String resolveUrl( String repositoryUrl, String tagBase, String subdir, ScmBranch branchTag )
{
...
// User has a tagBase specified so just return the name appended to the tagBase
if ( StringUtils.isNotEmpty( tagBase ) && !tagBase.equals( resolveTagBase( repositoryUrl ) )
&& !tagBase.equals( resolveBranchBase( repositoryUrl ) ) )
{
return appendPath( tagBase, branchTagName );
}
...
return addSuffix( appendPath( appendPath( projectRoot, subdir ), branchTagName ), queryString );
}
The !tagBase.equals( resolveBranchBase( repositoryUrl) ) condition prevents the tagBase from being used if it matches the standard /branches/ directory in the SVN repository layout. I was even able to test this out using a different tagBases that didn't match the /branches/ directory (for example, http://svn.server/svn/repo/.../project/releases) and it worked as expected.
Unfortunately, I'm still not 100% sure about the best way to have the releases written to /branches/ when running mvn release:prepare. I'm thinking I might just modify that bit of code in maven-scm-provider-svn-commons and figure out a way to get the maven-release-plugin to use my modified version of svn-commons.
Anyways, I hope this might help anyone who's trying to do something similar with the maven-release-plugin.

How to enforce the use of exactly one out of two Maven profiles?

I have a Maven project that defines two separate profiles, developer and release (surely you get the drift, here). I want one of these two profiles to be activated at any time, but never both. If both are somehow activated, this build makes no sense and should fail. If neither is activated, this build also makes no sense and should fail.
I'm sure I can write some custom plugin code to achieve this, and I might very well end up going that way, but I'd be interested in achieving this using POM configuration (could be using existing plugins from Maven Central).
It should be possible to activate plugins using -P (--activate-profiles) so <activation> through properties would not be a valid solution. Solutions using activeByDefault would not be valid either, since activeByDefault is generally known as a pitfall, unreliable (and we may in fact activate other profiles, thus rendering activateByDefault unusable).
Your suggestions much appreciated.
I had a similar need (i.e. for mutual exclusivity of two profiles) and solved it by considering the two target profiles to be internal profiles that shouldn't be specified on the command line: Instead, a controlling system property can either be specified or not. E.g. let's assume that by default you want the "dev" profile to be active. We can then activate/deactivate the relevant internal profiles based on whether the -Drelease option is specified as follows:
<!-- Internal profile: FOR INTERNAL USE ONLY - active if -Drelease is *not* specified. -->
<profile>
<id>internal-dev</id>
<activation>
<!-- Activation via *absence* of a system property to ensure mutual exclusivity
of this profile with internal-release -->
<property>
<name>!release</name>
</property>
</activation>
...
</profile>
<!-- Internal profile: FOR INTERNAL USE ONLY - active if -Drelease *is* specified. -->
<profile>
<id>internal-release</id>
<activation>
<!-- Activation via *presence* of a system property to ensure mutual exclusivity
of this profile with internal-dev -->
<property>
<name>release</name>
</property>
</activation>
...
</profile>
The simplest solution for this kind of problem would be to use the maven-enforcer-plugin which exactly has such a rule to force to activate at least one of two or more profiles.
Unfortunately the requireActiveProfile has currently a bug. But currently a preparation for a new release is on going which solves this.
Update The bug mentioned above has been fixed in release 1.4 (which was released in 2015).
This can still be done with Maven Enforcer plugin
Although mutual exclusion, <requireActiveProfile>...<all>false</all>... is buggy as reported by #khmarbaise, there's still the <evaluateBeanshell/> built-in rule that lets one do whatever he wants.
I wrote one especially for this case: XOR of two profiles. I hope it helps.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-PROFILE_ONE-XOR-PROFILE_TWO-is-active</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireActiveProfile>
<profiles>PROFILE_ONE,PROFILE_TWO</profiles>
<all>false</all>
</requireActiveProfile>
<evaluateBeanshell>
<condition><![CDATA[
// ensure PROFILE_ONE XOR PROFILE_TWO
print("Checking if only one of PROFILE_ONE and PROFILE_TWO profiles is active ...");
boolean profile1 = false, profile2 = false;
for(s: "${project.activeProfiles}".replaceAll("\\[?\\s?Profile \\{id: (?<profile>\\w+), source: \\w+\\}\\]?", "${profile}").split(",")) {
if("PROFILE_ONE".equalsIgnoreCase(s)){ profile1 = true;}
if("PROFILE_TWO".equalsIgnoreCase(s)){ profile2 = true;}
}
print("PROFILE_ONE XOR PROFILE_TWO: "+(profile1 != profile2));
return profile1 != profile2;
]]></condition>
</evaluateBeanshell>
</rules>
<failFast>true</failFast>
</configuration>
</execution>
</executions>
</plugin>
The tricky part is looping over active profiles, which I've already done here. You can extend it to more than two profiles if you need. But you'll have to write the long xor expression, since beanshell doesn't implement Java xor ^ operator.
I always issue a build command like so:
mvn package -P-dev,prod
It explicitly disables the dev profile and enables the production one. To my knowledge, you can not conditionally enable one build profile if another is active (which is a bit unfortunate), and because of that you can't ensure that the profiles are mutually exclusive.
I needed a slightly more advanced version of this rule. I ended up writing it myself. I've submitted a patch to them that includes the following 2 rules:
The ability to specify a set of mutually-exclusive profiles (p1,p2:p1,p3 would mean p1 can't be active with either p2 or p3).
The ability to ban profiles (the contrary of requireActiveProfile). p1, p2 would mean neither p1 nor p2 can be active for this build.
Both of these rules support wildcards and consider inherited profiles as well. These are built on v1.4 of the rules.
http://jira.codehaus.org/browse/MENFORCER-225

Slash in property name in pom.xml

I have a problem, what I cannot solve.
I want to build my eclipse cdo server with Tycho/Maven and also I want to have the prossibility to start my cdo-server.product out of eclipse.
The cdo server it set up like this: http://wiki.eclipse.org/Setting_up_a_CDO_Server
No there is my problem:
If I choose:
-Dnet4j.config="${resource_loc:/cdo.server/config}"
I can start it out of eclipse, but if I want to start the built CDO-Server.app it cannot find this folder.
If I choose:
-Dnet4j.config="../../../../../../../../../../cdo.server/config"
I can start the built CDO-Server.app, but I can't start it ou of eclipse.
This is all logical, but now I decided to make ${resource_loc:/cdo.server/config} as a property in my pom.xml file.
But if I write it like this:
<properties>
<resource_loc:/cdo.server/config>../../../../../../../../../../cdo.server/config</resource_loc:/cdo.server/config>
</properties>
I get the exception, that this is not a parseable POM because of the slash in the tag.
If I want to make it like this:
<properties>
<resource_loc:>
<cdo.server>
<config>../../../../../../../../../../cdo.server/config</config>
</cdo.server>
</resource_loc:>
</properties>
It also is not a parseable POM. Is there any possibility to use ${resource_loc:/cdo.server/config} as a property?
The problem in your property definition are the slashes in the name of the property.
The following will fail parsing the pom.xml:
<resource_loc:/cdo.server/config>yx</resource_loc:/cdo.server/config>
or
WhatEverValue
It will also not working if you try to use / as a replacement for the slash in the entity name.
you may want to try http://mojo.codehaus.org/properties-maven-plugin/read-project-properties-mojo.html to read the properties from a separate file instead in order to get around the XML well-formedness limitation in pom.xml.

Resources