Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure encoding for different filetypes in maven?

Tags:

encoding

maven

I use the maven-resource-plugin to filter some resources in my maven project. In my parent project I have:

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

In a sub project I have a test.properties file which is a plain java properties file with default encoding=ISO-8859-1. This file contains:

aboutText=Version ${project.version} © 2012 blabla

To make sure this file filters correctly I have split the maven-resource-plugin into separate executions each with its encoding:

  <plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
      <nonFilteredFileExtensions>
        <nonFilteredFileExtension>ico</nonFilteredFileExtension>
        <nonFilteredFileExtension>jar</nonFilteredFileExtension>
      </nonFilteredFileExtensions>
    </configuration>
    <executions>
      <execution>
        <id>filter-properties-files</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>copy-resources</goal>
        </goals>
        <configuration>
          <!-- java properties files are encoded in ISO-8859-1 so when 
            filtering those files we stick with that encoding. -->
          <encoding>ISO-8859-1</encoding>
          <outputDirectory>${basedir}/after</outputDirectory>
          <resources>
            <resource>
              <filtering>true</filtering>
              <directory>${basedir}/before</directory>
              <includes>
                <include>**/*.properties</include>
              </includes>
            </resource>
          </resources>
        </configuration>
      </execution>
      <execution>
        <id>filter-non-properties-files</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>copy-resources</goal>
        </goals>
        <configuration>
          <encoding>${project.build.sourceEncoding}</encoding>
          <outputDirectory>${basedir}/after</outputDirectory>
          <resources>
            <resource>
              <filtering>true</filtering>
              <directory>${basedir}/before</directory>
              <includes>
                <include>**/*.product</include>
                <include>**/*.inf</include>
              </includes>
            </resource>
          </resources>
        </configuration>
      </execution>
    </executions>
  </plugin>

This seems overkill and I have a feeling that I am either not using the plugin correctly or that this problem should be handled in another way. Maybe stick to encoding special characters in properties files directly:

aboutText=Version ${project.version} \u00a9 2012 blabla

?

like image 580
so12345 Avatar asked Jun 21 '12 18:06

so12345


1 Answers

The question is an invaluable answer in itself, as apparently the complicated procedure the author provides is the only way to configure different encodings for various filtered file types. The example given, however, is specific to the author's non-standard use-case, and glosses over a few important details, without which actual use of the example is fraught with gotchas:

  • It isn't obvious, but in the author's example the default resource copying goal resources is still enabled and runs in addition to the two defined goals!
  • You'll notice that the author used the lifecycle phase generate-resources instead of the default process-resources. This is a trick to get around the first point above; by making the two copy-resources goals occur in an earlier lifecycle phase, the resources are copied according to the given rules, and then when the default-resources goal comes along the original resource copying is left intact, apparently because its overwrite setting defaults false. But it would be better to disable altogether the default-resources execution.
  • The author provides an outputDirectory declaration. It would be natural to think that the author only provided this because a custom output directory was desired; after all, the resources goal provides a default value for this setting. Strangely, though, for the copy-resources goal this setting is actually required! There is a standard Maven variable ${project.build.outputDirectory} which can be used as the value, however.

Building on the author's own example in the question, here is a cut-and-paste way to filter properties files using ISO-8859-1, copy other files without filtering, and prevent the default resource copying from occurring; all using the standard source and target directories:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>2.7</version>
  <executions>
    <execution>
      <!-- Turn off default resource copying. -->
      <id>default-resources</id>
      <phase />
    </execution>
    <execution>
      <!-- Filter resources in properties files. -->
      <id>filter-properties-files</id>
      <phase>process-resources</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <encoding>ISO-8859-1</encoding>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.properties</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
    <execution>
      <!-- Do not do property substitution in files that are not properties files, such as binary files. -->
      <id>copy-other-resources</id>
      <phase>process-resources</phase>
      <goals>
        <goal>copy-resources</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
              <exclude>**/*.properties</exclude>
            </excludes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Update: After more research, I believe that instead of disabling the default execution, one could simply modify the default execution to ignore properties files, and add filtering of properties files as an additional execution. Moreover if the resources goal were used instead of copy-resources, there would be no need to indicate an output directory or a phase, as resources:resources automatically binds to the process-resources phase and outputs to ${project.build.outputDirectory}. Note that I've updated to version 3.1.0 of the plugin, so perhaps some of these options were not available in the version I used above. I have not tested this new, shorter configuration.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-resources-plugin</artifactId>
  <version>3.1.0</version>
  <executions>
    <execution>
      <!-- Ignore properties files by default. -->
      <id>default-resources</id>
      <configuration>
        <resources>
          <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <excludes>
              <exclude>**/*.properties</exclude>
            </excludes>
          </resource>
        </resources>
      </configuration>
    </execution>
    <execution>
      <!-- Filter resources in properties files using ISO-8859-1. -->
      <id>filter-properties-files</id>
      <goals>
        <goal>resources</goal>
      </goals>
      <configuration>
        <encoding>ISO-8859-1</encoding>
        <resources>
          <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.properties</include>
            </includes>
          </resource>
        </resources>
      </configuration>
    </execution>
  </executions>
</plugin>

Maybe someone could test this new configuration and let me know if it works the same as the original one I gave above.

like image 82
Garret Wilson Avatar answered Oct 07 '22 18:10

Garret Wilson