Плагин Gradle с JavaExecHandleBuilder не читает из System.in
Я пишу плагин Gradle, который должен запускать процесс Java, который читает с консоли через System.in. Но не читает, видимо, InputStream не блокирует. Какие вызовы API мне нужно делать?
В файле build.gradle для этого необходимо указать "standardInput = System.in". Я сделал эквивалент в коде плагина:
JavaExecHandleBuilder javaCommand = builder.getJavaCommand();
// here the standardInput is set
javaCommand.setStandardInput(System.in);
Также запуск Gradle с "--no-daemon" не приносит успеха.
Задача Gradle:
public class DataProcessing extends DefaultTask {
private final ConfigurableFileCollection dataFiles;
private String jqaTask;
private List<String> args = new ArrayList<>();
public DataProcessing() {
dataFiles = getProject().files();
}
@InputFiles
public FileCollection getDataFiles() {
return dataFiles;
}
public void setDataFiles(FileCollection dataFiles) {
this.dataFiles.setFrom(dataFiles);
}
@Inject
public Instantiator getInstantiator() {
throw new UnsupportedOperationException();
}
@Inject
public WorkerProcessFactory getWorkerProcessBuilderFactory() {
throw new UnsupportedOperationException();
}
@TaskAction
public void process() {
DataProcessingWorkerManager manager = new DataProcessingWorkerManager();
DataProcessingResult result = manager.runWorker(getProject().getProjectDir(), getWorkerProcessBuilderFactory(), getDataFiles(), createSpec());
}
private DataProcessingSpec createSpec() {
return new DataProcessingSpec()
.withArgs(args.toArray(new String[0]));
}
public void addArg(String arg) {
args.add(arg);
}
}
Вызываемый DataProcessingWorkerManager:
public class DataProcessingWorkerManager {
public DataProcessingResult runWorker(File workingDir, WorkerProcessFactory workerFactory, FileCollection classpath, DataProcessingSpec spec) {
try {
DataProcessingWorker worker = createWorkerProcess(workingDir, workerFactory, classpath, spec);
return worker.run(spec);
} catch (WorkerProcessException e) {
System.err.println(e);
return new DataProcessingResult();
}
}
private DataProcessingWorker createWorkerProcess(File workingDir, WorkerProcessFactory workerFactory, FileCollection classpath, DataProcessingSpec spec) {
SingleRequestWorkerProcessBuilder<DataProcessingWorker> builder = workerFactory.singleRequestWorker(DataProcessingWorker.class, DataProcessingExecutor.class);
builder.setBaseName("Gradle DataProcessing Worker");
builder.applicationClasspath(classpath);
JavaExecHandleBuilder javaCommand = builder.getJavaCommand();
javaCommand.setWorkingDir(workingDir);
javaCommand.setDefaultCharacterEncoding("UTF-8");
javaCommand.setIgnoreExitValue(true);
// here the standardInput is set
javaCommand.setStandardInput(System.in);
javaCommand.setStandardOutput(System.out);
javaCommand.setErrorOutput(System.err);
return builder.build();
}
}
public class DataProcessingExecutor implements DataProcessingWorker {
@Override
public DataProcessingResult run(DataProcessingSpec spec) {
System.out.println("Reading from System.in");
try {
final int read = System.in.read();
if(read == -1) {
System.out.println("End of stream.");
} else {
System.out.println("Read a character: "+read);
}
} catch (Exception e) {
System.err.println("An error occured: "+e);
}
return new DataProcessingResult();
}
}
При вызове задачи ожидается, что будет напечатано "Чтение из System.in", и задача ожидает ввода. Но вместо "Конец потока". происходит немедленно, и задача завершается. При выполнении "System.in.read()" не в исполняемом коде JavaExecHandleBuilder, а непосредственно в потоке плагина, он работает должным образом. Полный журнал:
./gradlew --no-daemon --info read Initialized native services in: C:\Users\jnerc\.gradle\native
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/5.2.1/userguide/gradle_daemon.html.
Starting process 'Gradle build daemon'. Working directory: C:\Users\jnerc\.gradle\daemon\5.2.1 Command: C:\Program Files\Java\jdk1.8.0_191\bin\java.exe -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx512m -Dfile.encoding=windows-1252 -Duser.country=DE -Duser.language=de -Duser.variant -cp C:\Users\jnerc\.gradle\wrapper\dists\gradle-5.2.1-all\bviwmvmbexq6idcscbicws5me\gradle-5.2.1\lib\gradle-launcher-5.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 5.2.1
Successfully started process 'Gradle build daemon'
An attempt to start the daemon took 1.036 secs.
The client will now receive all logging from the daemon (pid: 3556). The daemon log file: C:\Users\jnerc\.gradle\daemon\5.2.1\daemon-3556.out.log
Daemon will be stopped at the end of the build stopping after processing
Using 16 worker leases.
Starting Build
Settings evaluated using settings file 'C:\Users\jnerc\projects\spikes\gradle-plugin\settings.gradle'.
Projects loaded. Root project using build file 'C:\Users\jnerc\projects\spikes\gradle-plugin\build.gradle'.
Included projects: [root project 'gradle-plugin']
> Configure project :
Evaluating root project 'gradle-plugin' using build file 'C:\Users\jnerc\projects\spikes\gradle-plugin\build.gradle'.
All projects evaluated.
Selected primary task 'read' from project :
Tasks to be executed: [task ':read']
:read (Thread[Execution worker for ':',5,main]) started.
Initialized native services in: C:\Users\jnerc\.gradle\native
> Task :read
Task ':read' is not up-to-date because:
Task has not declared any outputs despite executing actions.
Starting process 'Gradle DataProcessing Worker 1'. Working directory: C:\Users\jnerc\projects\spikes\gradle-plugin Command: C:\Program Files\Java\jdk1.8.0_191\bin\java.exe -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=DE -Duser.language=de -Duser.variant -cp C:\Users\jnerc\.gradle\caches\5.2.1\workerMain\gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle DataProcessing Worker 1'
Successfully started process 'Gradle DataProcessing Worker 1'
Reading from System.in
End of stream.
:read (Thread[Execution worker for ':',5,main]) completed. Took 0.988 secs.
BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed