Shell Command to Update Pom File from a Variable

Bash script to update text between tags in a pom file?

Since the question was tagged sed, I suppose awk would be a valid alternative.

In this case you could process the pom file in awk, save the result in a tmpfile and overwrite the original file with the modified version:

#!/bin/sh

# error function
error(){
echo -e >&2 "error: $@"
exit 1
}

update_rpm_release_in_pom()
{
#################
# set constants #
#################

POM_FILE="./template/iptools/pom.xml"
USAGE="usage: update_rpm_release_in_pom <build num>"

#################
# sanity checks #
#################

# argument given?
[[ $# -eq 1 ]] || \
error "wrong number of parameters\n$USAGE"

# pom file exists?
[[ -e "$POM_FILE" ]] || \
error "pom file $POM_FILE does not exist"

# pom file readable?
[[ -r "$POM_FILE" ]] || \
error "pom file $POM_FILE is not readable"

# pom file writeable?
[[ -w "$POM_FILE" ]] || \
error "pom file $POM_FILE is not writeable"

##################
# set parameters #
##################

BUILD_NUM=$1

###############################
# create temporal output file #
# and ensure its removal #
###############################

# cleanup function
cleanup(){
[[ -e "$TMP_FILE" ]] && rm -- "$TMP_FILE"
}

# ensure cleanup on exit
trap 'cleanup' EXIT

# create temporal output file or exit with error
TMP_FILE=`mktemp` || \
error "could not create temporal output file"

#############################
# process pom file with awk #
# and save modified version #
# in temporal output file #
#############################

awk \
-F "rpm.release>" \
-v OFS="rpm.release>" \
-v BUILD_NUM="$BUILD_NUM" \
'
/<properties>/{
properties=1
}
/<\/properties>/{
properties=0
}
properties&&$1~/<$/&&$2~/<\/$/{
$2=BUILD_NUM"</"
}
1
' "$POM_FILE" > "$TMP_FILE" || \
error "processing pom file $POM_FILE with awk failed"

#########################
# move modified version #
# back to original path #
#########################

mv -- "$TMP_FILE" "$POM_FILE" || \
error "could not mv temporal output file $TMP_FILE to pom file $POM_FILE"
}

# Call above function
update_rpm_release_in_pom 11

Note that this should work with all versions of awk since there are no GNUisms in there.

There might be a way to do this in sed and get around the tmpfile stuff by using sed's inplace (-i) option, but a) I am not sure how to do this in a safe way in sed and b) I do not even know if you run a version of sed that supports the -i option.

In case you need further help, adjustments and/or explanations, feel free to add a comment.

Addendum:

In case you really need to do this without any script language, I modified your code and substituted my awk code with that:

#!/bin/bash

# error function
error(){
echo -e >&2 "error: $@"
exit 1
}

update_rpm_release_in_pom()
{
#################
# set constants #
#################

POM_FILE="./template/iptools/pom.xml"
USAGE="usage: update_rpm_release_in_pom <build num>"

#################
# sanity checks #
#################

# argument given?
[[ $# -eq 1 ]] || \
error "wrong number of parameters\n$USAGE"

# pom file exists?
[[ -e "$POM_FILE" ]] || \
error "pom file $POM_FILE does not exist"

# pom file readable?
[[ -r "$POM_FILE" ]] || \
error "pom file $POM_FILE is not readable"

# pom file writeable?
[[ -w "$POM_FILE" ]] || \
error "pom file $POM_FILE is not writeable"

##################
# set parameters #
##################

BUILD_NUM=$1

###############################
# create temporal output file #
# and ensure its removal #
###############################

# cleanup function
cleanup(){
[[ -e "$TMP_FILE" ]] && rm -- "$TMP_FILE"
}

# ensure cleanup on exit
trap 'cleanup' EXIT

# create temporal output file or exit with error
TMP_FILE=`mktemp` || \
error "could not create temporal output file"

##############################
# process pom file with bash #
# and save modified version #
# in temporal output file #
##############################

BEGIN_PROPERTIES="n"
while read LINE
do
case $BEGIN_PROPERTIES in
n) # <property> tag not found yet
[[ "$LINE" == *\<properties\>* ]] && BEGIN_PROPERTIES="y"
echo "$LINE"
continue
;;
y) # <property> tag found
[[ "$LINE" == *\</properties\>* ]] && BEGIN_PROPERTIES="n"
if [[ "$LINE" == *rpm.release* ]]; then
# Update value
echo "${LINE/<rpm\.release>*<\/rpm\.release>/<rpm.release>$BUILD_NUM<\\rpm.release>}"
continue
fi
echo "$LINE"
;;
esac
done < "$POM_FILE" > "$TMP_FILE" || \
error "processing pom file $POM_FILE with bash failed"

#########################
# move modified version #
# back to original path #
#########################

mv -- "$TMP_FILE" "$POM_FILE" || \
error "could not mv temporal output file $TMP_FILE to pom file $POM_FILE"
}

# Call above function
update_rpm_release_in_pom 11

However, this is not as stable as the above solution.
For example, on my machine this removes the leading whitespace from the pom file.
I do not know whether this is due to some quoting problem or if you'd need to adjust parameters of read or echo.
Since I would never use such a soultion I will not further investigate on this but maybe this helps you in case you insist on a bash-only solution.

How to variablize shell script output on maven pom.xml to use

Here is a suggested approach:

  • Use the Exec Maven Plugin for launching your script or commands
  • Use the Properties Maven Plugin to load the configuration

Requirements for this approach:

  • The curl response you expect (or the output or your script) should have a name=value format (that is, a properties file)
  • The Exec Maven Plugin execution must be declared in your POM before the Properties Maven Plugin execution and they must be attached to the same Maven phase or to two consecutive Maven phases in order to provide the desired flow
  • The Properties Maven Plugin execution must be attached to an early phase of Maven (initialize or validate) in order to make the configuration available to other Maven phases and plugins

For a complete list of Maven phases, official documentation here

Update: below an example of flow, just tested and work perfectly (on Windows machine):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>generation</artifactId>
<version>0.0.1-SNAPSHOT</version>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>retrieve-config</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>echo</executable>
<arguments>
<argument>jar.name=from-exec</argument>
<argument>></argument>
<argument>config.properties</argument>
</arguments>
<workingDirectory>${basedir}/src/main/resources/</workingDirectory>
</configuration>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<id>read-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${basedir}/src/main/resources/config.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>${jar.name}</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>

Basically, the exec plugin attached to the validate phase will be executed at the beginning of the build, writing to a config.properties file (via the echo command) the content jar.name=from-exec.

Then the properties plugin attached to the initialize phase will read that config.properties file and load the properties to be used as part of the build.

Then, as an example, the jar plugin will use that property as part of its configuration (the <finalName>${jar.name}</finalName> part).

Running mvn clean package, you will find the from-exec.jar file in the target folder.

Update: Above is an example of how to load dynamically from a script a set of properties which can then be injected into a Maven build (hence used as part of the POM configuration).

However, if you need to load this dynamic configuration into your application, you can even skip the second step (the Propeprties Maven Plugin) and load the properties from the config.properties file in your code, as long as the file is part of the application classpath (like in the example above, placed under src/main/resources).

Since the creation of the properties file happens on early Maven phase (validate or initialize), the test (for your tests) and package (for your final artefact) phases could then use it as required.

In Java, you would use the java.util.Properties class, in Groovy you can follow the explanation here, from another question in stackoverflow.

Update a Maven project version from script

I was wondering if there is any maven plugin that would be able to modify the pom.xml directly from the command line.

The Versions Maven Plugin can do this. Check the following goal:

  • versions:set can be used to set the project version from the command line, updating the details of any child modules as necessary.

maven update pom property

mvn versions:update-properties -Dproperties=[XYZ] -DincludeProperties={abc.def}

Read more here.
and here.

In short:

In versions-maven-plugin, the update-properties goal sets properties to the latest versions of specific artifacts.

includeProperties is a comma separated list of properties to update.

properties are any restrictions that apply to specific properties.

How to get Maven project version to the bash command line

The Maven Help Plugin is somehow already proposing something for this:

  • help:evaluate evaluates Maven expressions given by the user in an interactive mode.

Here is how you would invoke it on the command line to get the ${project.version}:

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
-Dexpression=project.version

As noted in the comments by Seb T, to only print the version without the maven INFO logs, additionally use -q -DforceStdout:

mvn help:evaluate -Dexpression=project.version -q -DforceStdout

How can I update a property in a Maven POM?

Is there a simple way to rewrite a Maven property entry to a specific value

Since version 2.5 we can use set-property (documentation):

mvn versions:set-property -Dproperty=your.property -DnewVersion=arbitrary_value

As documented, the set-property goal does not perform any 'sanity checks' on the value you specify, so it should always work, but you should use with care.



Related Topics



Leave a reply



Submit