Search code examples
xmlmavenmaven-3maven-jar-plugin

Is it possible to change (or add) a custom keyed Class-path entry in the Manifest?


While using the maven-jar-plugin: is it possible to create a custom classpath key entry in the Manifest with the same content as Class-Path? e.g. in this case Cluster-Dependencies:

Manifest-Version: 1.0
Class-Path: scala-library-2.10.6.jar scalatest_2.10-3.0.0.jar
Cluster-Dependencies: scala-library-2.10.6.jar scalatest_2.10-3.0.0.jar

and the relevant section from the pom.xml

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.0.2</version>
      <configuration>
        <archive>
          <index>true</index>
          <manifest>
            <addClasspath>true</addClasspath>
          </manifest>
          <manifestEntries>
            <Cluster-Dependencies>???</Cluster-Dependencies>
          </manifestEntries>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

Solution

  • This is how I achieved it:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
            <execution>
                <id>unpack</id>
                <phase>validate</phase>
                <goals>
                    <goal>build-classpath</goal>
                </goals>
                <configuration>
                    <outputProperty>classpath.entry</outputProperty>
                    <pathSeparator>;</pathSeparator>
                    <prefix>:</prefix>
                    <fileSeparator>_</fileSeparator>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
            <execution>
                <id>regex-property</id>
                <goals>
                    <goal>regex-property</goal>
                </goals>
                <configuration>
                    <name>classpath.entry.tmp</name>
                    <value>${classpath.entry}</value>
                    <regex>_</regex>
                    <replacement xml:space="preserve"> </replacement>
                    <failIfNoMatch>false</failIfNoMatch>
                </configuration>
            </execution>
            <execution>
                <id>regex-property2</id>
                <goals>
                    <goal>regex-property</goal>
                </goals>
                <configuration>
                    <name>classpath.entry.tmp2</name>
                    <value>${classpath.entry.tmp}</value>
                    <regex>;</regex>
                    <replacement></replacement>
                    <failIfNoMatch>false</failIfNoMatch>
                </configuration>
            </execution>
            <execution>
                <id>regex-property3</id>
                <goals>
                    <goal>regex-property</goal>
                </goals>
                <configuration>
                    <name>classpath.entry.final</name>
                    <value>${classpath.entry.tmp2}</value>
                    <regex>:</regex>
                    <replacement></replacement>
                    <failIfNoMatch>false</failIfNoMatch>
                </configuration>
            </execution>                    
        </executions>
    </plugin>
    <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
            <archive>
                <index>true</index>
                <manifest>
                    <addClasspath>true</addClasspath>
                </manifest>
                <manifestEntries>
                    <Cluster-Dependencies>${classpath.entry.final}</Cluster-Dependencies>
                </manifestEntries>
            </archive>
        </configuration>
    </plugin>       
    

    Its verbosity is mainly due to the impossibility of defining spaces or empty characters for the build-classpath goal (or at least I couldn't easily make it), hence several regex are applied to achieve it on the final ${classpath.entry.final} property which will contain the project classpath and can then be used as a placeholder of the Manifest entry.

    Also note the usage of the xml:space="preserve" attribute in the regex replacement, without it there was no way of applying a space as file separator.