Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven replacer: replacement value containing dollar signs

I am dealing with a Maven script where I have to modify some file content. I am currently using the replacer plugin, which gives me trouble when the replacement value contains dollar signs.

The replacement I have problems with is relatively simple: in my log4j.xml, replace the line <param name="File" value="wat.log" />with <param name="File" value="${FOO_BAR}/wat.log" />

I know that, written like that, Maven would interpret ${FOO_BAR} as property. I looked up a solution and tried it. When I just use ${FOO}

<properties>
    <dollar>$</dollar>
    <foo>{FOO_BAR}</foo>
    <dollar.foo>${dollar}${foo}</dollar.foo>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>com.google.code.maven-replacer-plugin</groupId>
            <artifactId>replacer</artifactId>
            <version>1.5.3</version>
            <executions>
                <execution>
                    <id>configure-logging</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>replace</goal>
                    </goals>
                    <configuration>
                        <includes>
                            <include>${my.configDir}/log4j.xml</include>
                        </includes>
                        <replacements>
                            <replacement>
                                <token>value="wat.log"</token>
                                <value>value="${dollar.foo}/wat.log"</value>
                            </replacement>
                        </replacements>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

The result is an error named capturing group is missing trailing '}'. As I understand it, the plugin uses the usual Java regex replacement which interprets dollar signs and curlies in the replacement text for capturing groups in the regex.

I tried a few other things, and it seems the specific error in this case is due to the underscore. If I change the foo property to {FOOBAR}, the error changes: No group with name {FOOBAR}.

I tried a few other things as well:

  • changing the foo property to {foo}, I don't get an error, but the replacement drops the $, i.e. I get value="{foo}/wat.log" - a second replacement of foo with FOO_BAR works, but I still am missing the dollar sign
  • changing the property to {dollar} gives me an Illegal group reference error
  • escaping the dollar, braces and/or underscores in several different ways (e.g. $$, \$, \\$) did not bring me any further, neither did using unicode or $ for the dollar sign.

Is there a way to actually solve this with Maven? I'd be happy to use more properties, more replacements or an entirely different plugin.

Update: I am working on Windows - not sure if/how that affects the results.

like image 449
Arne Mertz Avatar asked Nov 12 '15 08:11

Arne Mertz


2 Answers

You are very close. Just prepend the $ character with an escaping back-slash:

...
<replacements>
  <replacement>
    <token>value="wat.log"</token>
    <value>value="\${dollar.foo}/wat.log"</value>
  </replacement>
</replacements>
...

log4j.xml, before:

<param name="File" value="wat.log" />

log4j.xml, after:

<param name="File" value="${FOO_BAR}/wat.log" />

It worked for me.

like image 151
Daniel Avatar answered Nov 06 '22 03:11

Daniel


I found the answer myself, looking for another problem related to backslashes: Add <regex>false</regex> to the configuration of the replacer plugin, then the replacer will just replace the plain text it sees and the ${dollar.foo} trick works as intended:

<properties>
    <dollar>$</dollar>
    <foo>{FOO_BAR}</foo>
    <dollar.foo>${dollar}${foo}</dollar.foo>
</properties>

...
                    <configuration>
                        <includes>
                            <include>${my.configDir}/log4j.xml</include>
                        </includes>


                        <!-- don't treat token/value as regular expressions -->
                        <regex>false</regex>


                        <replacements>
                            <replacement>
                                <token>value="wat.log"</token>
                                <value>value="${dollar.foo}/wat.log"</value>
                            </replacement>
                        </replacements>
                    </configuration>
...
like image 33
Arne Mertz Avatar answered Nov 06 '22 04:11

Arne Mertz