Плагин Gradle с JavaExecHandleBuilder не читает из System.in - PullRequest
0 голосов
/ 19 октября 2019

Я пишу плагин 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
...