Best practice for copying files from classpath

Sorry if this has been asked before, the topic is not easy to search on the forum (or web).

My custom plugin contains some resources that I like to copy to the projects that apply it. While this is trivial in pure Groovy, I would like to use the Copy DSL to do so.

Looking at the ‘Copy’ and ‘Project.files()’, they are mostly ‘File’-centric and do not accept ‘InputStream’ or ‘URI’ that go through JARs (not hierarchal). Is there a recommended approach to do this, leveraging existing Gradle tasks?

I suppose it depends how these resources are being added to the classpath. Is the resource part of your project source or is it in an external dependency?

My specific scenario is that I have a stand-alone custom plugin project which houses some template files as resources. This plugin is packaged as a JAR, available in a private repo to be pulled by concrete projects.

A task in this plugin needs to copy these template files (from classpath) to concrete project’s ‘buildDir’ and do some processing on them. I was hoping there was a way I could leverage ‘Copy’ and Ant filters but I am not quite sure how. Or if alternatively there are some built-in tasks that can deal with streams, as oppose to files.

Got it. Like you said, most of Gradle’s APIs are based around 'File’s. That being said, you might be able to use the new ‘TextResource’ mechanism to grab the necessary file(s) from the build script classpath configuration.

def resource = resources.text.fromArchiveEntry(buildscript.configurations.classpath, “org/foo/templates/some.template”)

Thanks for the tip. For posterity, this is what I ended up doing in my plugin after updating to 2.2.1:

‘’’ project.task(‘something’, type: Copy) {

from project.resources.text.fromArchiveEntry(

project.buildscript.configurations.classpath.findAll { it.name.contains ‘plugin-name’ },

‘template.file’).asFile()

into project.buildDir

… } ‘’’

It’s a bit verbose so I’ll probably make it a common function. Also I had to filter out my dependencies since ‘fromArchiveEntry()’ expects a collection with a single file.

Any plans to allow ‘Project.files()’ to accept ‘TextResource’?

I believe there are plans to make the resources API much more expressive. One thing you might consider is separating your plugin “resources” into a separate artifact that your plugin then adds as a dependency to a custom project configuration. There are a couple benefits to this like a) not having to filter out all the other artifacts on the ‘classpath’ configuration and b) not having to resolve (read: download) the resources until they are actually used.

Two things: 1) ‘find()’ is probably better than ‘findAll()’. 2) You want to defer the file value to project execution phase (i.e. wrap it in a closure), since if it is during project evaluation, a ‘clean’ task will remove the expanded archives.