Search code examples
javamavenvelocity

How can I override remote resources when building Maven?


I'm trying to build Maven 3.5.2 from source. (Reason: I'm on a machine which has Maven 3.0.5 installed, but is not allowed to download binaries (except for Maven dependencies), and I need a later version of Maven, so I'm planning to use Maven 3.0.5 to build Maven 3.5.2. According to the docs, this is possible.)

The machine I'm using to build also cannot access the internet.

The Maven build tries to access the Apache license from apache.org and fails if the license file cannot be downloaded. In particular, here is the tail end of the build output (which is running as root, albeit under SElinux):

[INFO] --- apache-rat-plugin:0.11:check (rat-check) @ apache-maven ---
[INFO] 51 implicit excludes (use -debug for more details).
[INFO] Exclude: src/test/resources*/**
[INFO] Exclude: src/test/projects/**
[INFO] Exclude: src/test/remote-repo/**
[INFO] Exclude: **/*.odg
[INFO] Exclude: src/bin/m2.conf
[INFO] Exclude: bootstrap/**
[INFO] Exclude: README.bootstrap.txt
[INFO] Exclude: .repository/**
[INFO] Exclude: .maven/spy.log
[INFO] Exclude: .java-version
[INFO] Exclude: README.md
[INFO] Exclude: DEPENDENCIES
[INFO] 19 resources included (use -debug for more details)
[INFO] Rat check: Summary of files. Unapproved: 0 unknown: 0 generated: 0 approved: 16 licence.
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:unpack-dependencies (unpack-jansi-native) @ apache-maven ---
[INFO] Unpacking /root/.m2/repository/org/fusesource/jansi/jansi/1.16/jansi-1.16.jar to /tmp/maven-build/apache-maven/target/dependency with includes "META-INF/native/**" and excludes ""
[INFO] 
[INFO] --- maven-remote-resources-plugin:1.5:process (default) @ apache-maven ---
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Apache Maven ...................................... SUCCESS [25.091s]
[INFO] Maven Model ....................................... SUCCESS [18.000s]
[INFO] Maven Artifact .................................... SUCCESS [4.418s]
[INFO] Maven Plugin API .................................. SUCCESS [4.677s]
[INFO] Maven Builder Support ............................. SUCCESS [1.900s]
[INFO] Maven Model Builder ............................... SUCCESS [5.690s]
[INFO] Maven Settings .................................... SUCCESS [1.905s]
[INFO] Maven Settings Builder ............................ SUCCESS [2.010s]
[INFO] Maven Repository Metadata Model ................... SUCCESS [1.511s]
[INFO] Maven Artifact Resolver Provider .................. SUCCESS [5.110s]
[INFO] Maven Core ........................................ SUCCESS [13.168s]
[INFO] Maven SLF4J Simple Provider ....................... SUCCESS [5.013s]
[INFO] Maven Embedder .................................... SUCCESS [3.617s]
[INFO] Maven Compat ...................................... SUCCESS [4.462s]
[INFO] Apache Maven Distribution ......................... FAILURE [4:18.467s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5:58.134s
[INFO] Finished at: Mon Feb 12 21:03:11 GMT 2018
[INFO] Final Memory: 83M/190M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-remote-resources-plugin:1.5:process (default) on project apache-maven: Error rendering velocity resource. Invocation of method 'getResourceAsFile' in  class org.codehaus.plexus.resource.DefaultResourceManager threw exception org.codehaus.plexus.resource.loader.ResourceNotFoundException: Could not find resource 'https://www.apache.org/licenses/LICENSE-2.0.txt'. at remote-resources[line 38, column 26] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR] 
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :apache-maven

I think maybe the remote resource plugin is something which is pulled in from the Apache parent POM, but I'm not sure, as I can't quite figure out how this works. That configuration seems to be pulling in a dependency apache-jar-resource-bundle which already contains the LICENSE.txt, so there would be no need to get it from the Internet.

Is there a way to disable the remote resource retrieval (perhaps in favour of a local resource), preferably by passing command-line arguments to Maven, but failing that, by modifying my local copy of Maven's root POM?


EDIT: Adding full stack trace. It seems that the method getResourceAsFile was called using reflection from Velocity, which made me think there must be a Velocity template referencing getResourceAsFile in one of the Apache artifacts, but I couldn't find anything in the repo at https://svn.apache.org/repos/asf/maven/resources/

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-remote-resources-plugin:1.5:process (default) on project apache-maven: Error rendering velocity resource. Invocation of method 'getResourceAsFile' in  class org.codehaus.plexus.resource.DefaultResourceManager threw exception org.codehaus.plexus.resource.loader.ResourceNotFoundException: Could not find resource 'https://www.apache.org/licenses/LICENSE-2.0.txt'. at remote-resources[line 38, column 26] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-remote-resources-plugin:1.5:process (default) on project apache-maven: Error rendering velocity resource.
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:414)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:357)
Caused by: org.apache.maven.plugin.MojoExecutionException: Error rendering velocity resource.
    at org.apache.maven.plugin.resources.remote.ProcessRemoteResourcesMojo.processResourceBundles(ProcessRemoteResourcesMojo.java:1246)
    at org.apache.maven.plugin.resources.remote.ProcessRemoteResourcesMojo.execute(ProcessRemoteResourcesMojo.java:520)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
    ... 19 more
Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getResourceAsFile' in  class org.codehaus.plexus.resource.DefaultResourceManager threw exception org.codehaus.plexus.resource.loader.ResourceNotFoundException: Could not find resource 'https://www.apache.org/licenses/LICENSE-2.0.txt'. at remote-resources[line 38, column 26]
    at org.apache.velocity.runtime.parser.node.ASTMethod.handleInvocationException(ASTMethod.java:243)
    at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:187)
    at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:280)
    at org.apache.velocity.runtime.parser.node.ASTReference.value(ASTReference.java:567)
    at org.apache.velocity.runtime.parser.node.ASTExpression.value(ASTExpression.java:71)
    at org.apache.velocity.runtime.parser.node.ASTSetDirective.render(ASTSetDirective.java:142)
    at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)
    at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:87)
    at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)
    at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:87)
    at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)
    at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:420)
    at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:207)
    at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)
    at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:420)
    at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:207)
    at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:342)
    at org.apache.velocity.runtime.RuntimeInstance.render(RuntimeInstance.java:1378)
    at org.apache.velocity.runtime.RuntimeInstance.evaluate(RuntimeInstance.java:1314)
    at org.apache.velocity.app.Velocity.evaluate(Velocity.java:254)
    at org.apache.maven.plugin.resources.remote.ProcessRemoteResourcesMojo.processResourceBundles(ProcessRemoteResourcesMojo.java:1218)
    ... 22 more
Caused by: org.codehaus.plexus.resource.loader.ResourceNotFoundException: Could not find resource 'https://www.apache.org/licenses/LICENSE-2.0.txt'.
    at org.codehaus.plexus.resource.DefaultResourceManager.getResource(DefaultResourceManager.java:173)
    at org.codehaus.plexus.resource.DefaultResourceManager.getResourceAsFile(DefaultResourceManager.java:91)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.doInvoke(UberspectImpl.java:395)
    at org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.invoke(UberspectImpl.java:384)
    at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:173)
    ... 41 more

EDIT 2: I think I found the culprit: https://github.com/apache/maven/blob/maven-3.5.2/apache-maven/src/main/appended-resources/META-INF/LICENSE.vm

It uses getResourceAsFile with the license URL.

But I don't know where this is pulled in from the remote resources plugin.

I'm not familiar with Apache Velocity. Can anyone help with how to override it?


NOTE: Not a duplicate of question 33548395, because that question is about dependency resolution, but this is about remote resources, which is different. The file being downloaded is not a Maven dependency, it's just a text file. The corresponding Maven dependency I would expect it to use is apache-jar-resource-bundle, but that dependency is already present in the remote repository I have access to, so I don't need to force Maven to read it locally. However it does seem that it tries to download the file directly rather than via a Maven dependency.


Solution

  • After realising that LICENSE.vm (and the one inside apache-maven, not the other one) was the problem (see my "EDIT 2"), I found that it also contains the solution. A URL for Glassfish is manually redirected to another and this is in the file at lines 32-35. So I thought I can do something similar for my scenario.

    First I worked out all the licenses and downloaded them. I gave them all .license extensions so I could tell Git to treat files with this extension as binary (via .gitattributes) so it wouldn't try to mess with the files by converting line endings, as I wanted to replicate what the actual build would do. There were only 5 files I actually needed to download in all.

    Secondly I created a little snippet to insert into the VM file; I called this license-redirect-snippet.vm:

    ## redirect all license URLs to local files
    #if ($url == "https://www.apache.org/licenses/LICENSE-2.0.txt")
    #set ( $url = '/usr/local/share/maven-build-licenses/apache2-txt.license' )
    #end
    #if ($url == "http://www.apache.org/licenses/LICENSE-2.0.txt")
    #set ( $url = '/usr/local/share/maven-build-licenses/apache2-txt.license' )
    #end
    #if ($url == "http://www.apache.org/licenses/LICENSE-2.0")
    #set ( $url = '/usr/local/share/maven-build-licenses/apache2-html.license' )
    #end
    #if ($url == "https://glassfish.java.net/public/CDDLv1.0.html")
    #set ( $url = '/usr/local/share/maven-build-licenses/cddl1-html.license' )
    #end
    #if ($url == "http://www.eclipse.org/legal/epl-v10.html")
    #set ( $url = '/usr/local/share/maven-build-licenses/epl1-html.license' )
    #end
    #if ($url == "http://www.opensource.org/licenses/mit-license.php")
    #set ( $url = '/usr/local/share/maven-build-licenses/mit-html.license' )
    #end
    

    NB: there is a new line at the end of the file.

    Then it was just a question of copying my licenses into the given folder (/usr/local/share/maven-build-licenses/) and using sed to modify the VM file before build, adding the snippet after line 35:

    sed -i '35r /tmp/license-redirect-snippet.vm' /tmp/maven-build/apache-maven/src/main/appended-resources/META-INF/LICENSE.vm
    

    After that, the build passes!!

    I probably could have come up with something better e.g. dynamically generating the snippet file based on the contents of the directory and some key-value pairs, or even rewriting the getResourceAsFile method so that this variable rewriting would not be needed, but that seems like overkill for such a simple case where there are only 5 licenses to deal with.