recently in the process of writing a gradle plug-in, when defining a file copy method for a task, the discovery file was not copied, it was a very simple operation, but there has been such a puzzled phenomenon. Because writing Gradle plugin debugging is not easy, so it took more time to find the problem, so this record.
The following is a compact version of the task class:
import java.io.file;import Java.util.list;import Java.util.concurrent.copyonwritearraylist;import Org.apache.commons.io.fileutils;import Org.gradle.api.tasks.taskaction;public class MyTask {private list<action> actions = new copyonwritearraylist< > ();p ublic void Copy (final string source, final string dest) throws Exception {This.actions.add (new Action () {@Override public void execute () throws Exception {fileutils.copyfile (new file (source), new file (dest));}) public void Copydependencies () {This.actions.add (new Action () {@Overridepublic void execute () throws Exception {File dir = New File ("H:\\sourcedir");//test Code Source directory for (File file:dir.listFiles ()) {copy (File.getabsolutepath (), "h:\\destdir\\" + File.getname ());}});} @TaskActionpublic void Execute () throws Exception {for (Action action:this.actions) {Action.execute ();}} public static interface Action {void execute () throws Exception;}}
In the code above, in order to unify the individual method calls, the method is invoked by simply adding an action to the Actions list, iterating through the actions when the task is actually executed, and then executing each action in turn. The copy and Copydependencies methods are called in the MyTask build script. If the list uses ArrayList instead of Copyonwritearraylist, the concurrentmodificationexception exception will be thrown during execution. Because ArrayList is not allowed to modify it during the iteration (adding or removing elements). However, even if the use of concurrentmodificationexception has not achieved the intended purpose, that is, file replication. After a closer look at the code, we found that although Copyonwritearraylist supports the iterative process of modifying the list, the Copy method in the Copydependencies method is intended to be used to reuse the copy method. And that's just adding a new action to the Actions list, not executing the action, so the file copy feature in the Copydependencies method is not valid.
Understand the cause of the problem for the post-improvement MyTask class:
Import Java.io.file;import java.util.list;import Java.util.arraylist;import Org.apache.commons.io.fileutils;import Org.gradle.api.tasks.taskaction;public class MyTask {private list<action> actions = new arraylist<> (); public void Copy (final string source, final string dest) throws Exception {This.actions.add (new Action () {@Overridepublic void execute () throws Exception {fileutils.copyfile (new file (source), new file (dest)),}}); public void Copydependencies () {This.actions.add (new Action () {@Overridepublic void execute () throws Exception {File dir = The new file ("H:\\sourcedir"), for (file File:dir.listFiles ()) {///no longer calls the Copy method, but directly to the file copy, thus avoiding adding elements to the Actions list only// The list type can also be used ArrayList fileutils.copyfile (file, new file ("h:\\destdir\\" +file.getname ()));}});} @TaskActionpublic void Execute () throws Exception {for (Action action:this.actions) {Action.execute ();}} public static interface Action {void execute () throws Exception;}}
Confusion about file copying