ProcessResources和筛选器内部的Gradle循环

ProcessResources和筛选器内部的Gradle循环,gradle,groovy,build.gradle,Gradle,Groovy,Build.gradle,在jar任务中,我想替换conf文件中的一些文本 jar { ext { excludedClasses = ["com.MyClass1", "com.MyClass2"] } doFirst { println 'Jar task started execution' println 'Excluded classes ' + excludedClasses exclude(excludedClasses

在jar任务中,我想替换conf文件中的一些文本

jar {
    ext {
        excludedClasses = ["com.MyClass1", "com.MyClass2"]
    }
    doFirst {
        println 'Jar task started execution'
        println 'Excluded classes ' + excludedClasses
        exclude(excludedClasses)
    }
    doLast {
        println 'Jar task finished execution'
    }
    processResources {
       filesMatching('**/moduleconfiguration/conf.json') { f ->
            excludedClasses.each { c ->
               filter {
                    println it
                    it.replace(c, "com.MyClass3")
               }
            }
        }
    }
}
但是上面的代码试图从所有*.class文件中替换c,从而导致非法jar。我希望它只在“**/moduleconfiguration/conf.json”文件中进行替换

我怎样才能做到这一点

更新

看来我也遇到了同样的问题:。此问题已经解决,但如果在
processResources
中使用
每个
循环,则会再次出现此问题

同时,我找到了两种解决我问题的方法,如下所示:

解决方案1:更改
过滤器
每个
循环的顺序。i、 e.在
过滤器内循环

filesMatching('**/moduleconfiguration/conf.json') { f ->
     filter {
        excludedClasses.each { c ->
            println it
            it = it.replace(c, "com.MyClass3")
       }
       it
    }
}
解决方案2:使用regex而不是
每个
循环

filesMatching('**/moduleconfiguration/conf.json') { f ->
     filter {
         println it
         def regex = excludedClasses.join("|")  // watch for .(dot) or other regex chars here
         it.replaceAll(regex, "com.MyClass3")
    }
}
我仍然想知道,如果在
filematching
方法闭包中使用
each
循环,为什么筛选范围会更改为所有文件。这是一个非常棒的东西还是渐变的东西?如果有人能解释那里发生了什么,我将非常感激

更新2

println
针对问题情况,在不同位置输出代表、此和所有者的值:

:processResources

Inside filesMatching. delegate:file '.../configuration/conf.json' this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90@6f3e18b8

Problematic Case inside loop before filter. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@4587ec31 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@4587ec31

Problematic Case inside loop before filter. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@4587ec31 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@4587ec31

:classes
:jar
Jar task started execution

Excluded classes [MyClass1.class, MyClass2.class]

Problematic Case inside loop inside filter. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@3a0d0128 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@3a0d0128
.
.
.
.
.
println
在解决方案1的不同位置输出代理、此和所有者的值:

:processResources

Inside filesMatching. delegate:file '.../configuration/conf.json' this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90@6ece61a3

Solution 1 Inside filter before loop. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@64af2ad7 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91@64af2ad7

Solution 1 Inside filter inside loop. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@22c74276 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@22c74276

Solution 1 Inside filter inside loop. delegate:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@22c74276 this:root project 'projectName' owner:build_95q5jrf5z5ao0hk03tsevn2t0$_run_closure10_closure90_closure91_closure92@22c74276
.
.
.
.
.
:classes
:jar
Jar task started execution
Excluded classes [MyClass1.class, MyClass2.class]
更新 根据你的第二次更新和我这边的一些测试,它似乎不是我最初建议的那样。这看起来确实是授权的问题,但我无法确定

您可以通过将
filter{
行更改为
f.filter{
,来说明原始(有问题)示例中的差异。这会显式尝试执行
FileCopyDetails#filter
方法,而不是范围内的任何方法

你应该可以看到,当调用<代码> f.Field时,只有匹配的文件被过滤。当你自己调用<代码>过滤器>代码>时,它调用了任务级一。但是,既然你已经处于拷贝文件的中间,它只会将过滤器应用到在匹配的第一个文件之后按字母顺序出现的文件。

例如,如果您有此文件夹结构:

+ resources/main
  - abc.json
  - configuration.json
  - def.json
  - efg.json
def.json
efg.json
将被过滤,但前两个不会被过滤

这仍然不能回答为什么它不调用正确的
过滤器
方法,但它至少确认它正在调用任务级别1

原始答案 我相信这是由于Groovy闭包委托给不同的对象造成的。我相信您实际上是在调用原始版本中的
Copy\filter
(有问题)两种解决方案中的大小写和
FileCopyDetails\filter
。复制任务的
filter
方法将对所有内容应用筛选器,而details
filter
方法将针对
filematching
中的特定文件

您应该能够通过打印出不同的代表来说明这些代表:

原创

processResources {
    filesMatching('**/moduleconfiguration/conf.json') { f ->
        excludedClasses.each { c ->
            // print the class of this closure's delegate
            println delegate.class
            filter {
                it.replace(c, "com.MyClass3")
            }
        }
    }
}
解决方案1

filesMatching('**/moduleconfiguration/conf.json') { f ->
     filter {
        // print the class of this closure's delegate
        println delegate.class
        excludedClasses.each { c ->
            println it
            it = it.replace(c, "com.MyClass3")
       }
       it
    }
}
我的期望是,您将看到原始的委托给您的任务(即,
processResources
)和委托给的解决方案。默认情况下,Groovy中的所有闭包都由声明它们的对象“拥有”,并且也将“委托”给所有者。当Gradle具有以闭包为参数的API时(例如
过滤器
方法),它们通常被重新配置为具有特定委托(通常是封闭的容器对象),并使用“委托优先”策略来查找方法


参见Groovy在上的文档。

对于原始版本和
类构建版本,脚本打印出
class build\u 95q5jrf5z5ao0hk03tsevn2t0$\u run\u closure10\u closure90\u closure91\u closure92
,对于解决方案1,脚本打印出
class build\u 95q5jrf5z5ao0hk03tsevn2t0$\u run\u closure90\u closure91
在问题中添加了一些println输出作为更新2。但是这些输出没有太大帮助。我注意到,在有问题的情况下,过滤器关闭在jar任务开始之后工作,在解决方案1中的jar任务开始之前工作。没有运气将其锁定,但请参阅我的更新以获取一些附加信息您是对的,使用
f.filter
solve调用过滤器我仍然需要时间来理解为什么会这样:)谢谢你的帮助。