Automatic Maven profile activation is very limited. The <os>
, <file>
, and <property>
options
are exact matches (you can't partial match or use regular expressions), and there's often no way to distinguish
between very different operating systems. For example, using these tags, you cannot differentiate between RedHat-like
systems and Debian/Ubuntu-like systems.
This Maven lifecycle extension (not a plugin—an extension) provides much finer-grained control over automatic profile activation, allowing you to check whether system properties, file contents, and/or command output contains certain values or matches certain regular expressions. Like the built-in profile activators, multiple finer activators are always AND-ed together. Additionally, you can AND built-in and finer activators together.
Contents
To "install" this extension, you must create a directory named .mvn
at the root of your project (at the same
level as your pom.xml
) and place a file named extensions.xml
with in. For example:
.mvn/ extensions.xml pom.xml src/ target/ ...
The contents of this file should be as follows (you may also/already have other extensions in this file):
<?xml version="1.0" encoding="UTF-8"?> <extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd"> <extension> <groupId>io.oddsource.java.maven</groupId> <artifactId>finer-profile-activation</artifactId> <version>[insert version here]</version> </extension> </extensions>
The version is required and cannot be parameterized. It's important to install the extension in this manner, because if
you install it directly within your pom.xml
, it will not be able to intercept profile activation.
By necessity, this extension re-uses the <property>
activator with magical prefixes to trigger the finer
activators.
To test that the os.name
property's contents, converted to lowercase, contains the given value:
<activation> ... <property> <name>[FINER.ACTIVATOR.CONTAINS]os.name</name> <value>mac</value> </property> ... </activation>
The given property must be a property available early in the Maven lifecycle (in other words, properties specified
in the pom.xml
file will not be matched).
To test that the os.version
property's contents match the given regular expression (case sensitive):
<activation> ... <property> <name>[FINER.ACTIVATOR.REGEX]os.version</name> <value>^.*\.el[0-9]{1,2}(_[0-9]+)?\..*$</value><!-- enterprise linux --> </property> ... </activation>
To test that the specified file exists, is accessible, and its contents contain the given value (case sensitive):
<activation> ... <property> <name>[FINER.ACTIVATOR.FILE.CONTAINS]/etc/os_release</name> <value>ID_LIKE=debian</value> </property> ... </activation>
By default, file contents are decoded in UTF-8. If this does not work, you can specify a different encoding, using any one of the character set names that Java supports:
<name>[FINER.ACTIVATOR.FILE.CONTAINS][ISO-8859-1]/etc/os_release</name>
To test that the specified file exists, is accessible, and its contents contain the given regular expression (case sensitive):
<activation> ... <property> <name>[FINER.ACTIVATOR.FILE.REGEX]/etc/os_release</name> <value>ID_LIKE="?(debian|fedora)"?</value> </property> ... </activation>
To test that the specified command exists, is accessible, is executable, and executes with any exit code, and its content contains the specified value (case sensitive):
<activation> ... <property> <name>[FINER.ACTIVATOR.SUBPROCESS.CONTENT]uname -a</name> <value>Linux</value> </property> ... </activation>
Arguments are separated by spaces and you can quote arguments that contain spaces, just like on the command line:
<name>[FINER.ACTIVATOR.SUBPROCESS.CONTENT]foo "bar baz" 'this is "one" argument'</name>
By default, process output is decoded in UTF-8. If this does not work, you can specify a different encoding, using any one of the character set names that Java supports:
<name>[FINER.ACTIVATOR.SUBPROCESS.CONTENT][ISO-8859-1]foo "bar baz" 'this is "one" argument'</name>
To test that the specified command exists, is accessible, is executable, and executes with any exit code, and its content matches the specified regular expression (case sensitive):
<activation> ... <property> <name>[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a</name> <value>^.*\.el[0-9]{1,2}(_[0-9]+)?\..*$</value><!-- enterprise linux --> </property> ... </activation>
To test that the specified command exists, is accessible, is executable, and executes with the exit code specified in the property value:
<activation> ... <property> <name>[FINER.ACTIVATOR.SUBPROCESS.REGEX]some_command --with-argument --and-another "foo bar baz"</name> <value>0</value> </property> ... </activation>
If you're having a hard time getting your finer activation rules to work, you can execute this command to view exhaustive debug output of this extension's evaluation of your rules:
$ mvn --debug help:active-profiles
You should see output like this that indicates how the extension is working:
[DEBUG] Property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' matches finer activator pattern. [DEBUG] Finer activator 'FINER.ACTIVATOR.FILE.CONTAINS' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.FILE.CONTAINS' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.FILE.REGEX' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.FILE.REGEX' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.CONTAINS' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.CONTAINS' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.REGEX' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.REGEX' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.EXIT' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.EXIT' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.CONTENT' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = false [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.CONTENT' INACTIVE [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.REGEX' applicable to property name '[FINER.ACTIVATOR.SUBPROCESS.REGEX]uname -a' = true [DEBUG] Finer activator 'FINER.ACTIVATOR.SUBPROCESS.REGEX' INACTIVE
This should enable you to figure out what's going on.