我正在编写一个Gradle插件,该插件需要剥离一个通过System.in从控制台读取的Java进程。但它不会读取,显然InputStream不会阻塞。我需要做什么API调用?
在build.gradle文件中,您需要为此指定“ standardInput = System.in”。 我在插件代码中做了同样的事情:
JavaExecHandleBuilder javaCommand = builder.getJavaCommand();
// here the standardInput is set
javaCommand.setStandardInput(System.in);
使用“ --no-daemon”运行Gradle也不会成功。
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读取”,并且任务等待输入。而是“流结束”。立即发生,任务结束。当不在JavaExecHandleBuilder执行的代码中而是直接在插件线程中执行“ System.in.read()”时,它会按预期工作。完整日志为:
./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