ExitCode (final CompileContext context, Map<ModuleBuildTarget, Collection<ClassItem>> remoteClasses, ModuleChunk chunk, OutputConsumer outputConsumer) { ExitCode exitCode = ExitCode.NOTHING_DONE; final Collection<File> classpath = ProjectPaths.getCompilationClasspath(chunk, false); final StringBuilder buf = new StringBuilder(); for (File file : classpath) { if (buf.length() > 0) { buf.append(File.pathSeparator); } buf.append(file.getPath()); } final String classpathString = buf.toString(); final String rmicPath = getPathToRmic(chunk); final RmicCompilerOptions options = getOptions(context); final List<ModuleBuildTarget> targetsProcessed = new ArrayList<>(remoteClasses.size()); for (Map.Entry<ModuleBuildTarget, Collection<ClassItem>> entry : remoteClasses.entrySet()) { try { final ModuleBuildTarget target = entry.getKey(); final Collection<String> cmdLine = createStartupCommand( target, rmicPath, classpathString, options, entry.getValue() ); final Process process = Runtime.getRuntime().exec(ArrayUtilRt.toStringArray(cmdLine)); final BaseOSProcessHandler handler = new BaseOSProcessHandler(process, StringUtil.join(cmdLine, " "), null) { @Override public @NotNull Future<?> executeTask(@NotNull Runnable task) { return SharedThreadPool.getInstance().submit(task); } }; final RmicOutputParser stdOutParser = new RmicOutputParser(context, getPresentableName()); final RmicOutputParser stdErrParser = new RmicOutputParser(context, getPresentableName()); handler.addProcessListener(new ProcessAdapter() { @Override public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) { if (outputType == ProcessOutputTypes.STDOUT) { stdOutParser.append(event.getText()); } else if (outputType == ProcessOutputTypes.STDERR) { stdErrParser.append(event.getText()); } } }); handler.startNotify(); handler.waitFor(); targetsProcessed.add(target); if (stdErrParser.isErrorsReported() || stdOutParser.isErrorsReported()) { break; } else { final int exitValue = handler.getProcess().exitValue(); if (exitValue != 0) { context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, JpsBuildBundle.message("build.message.rmi.stub.generation.failed"))); break; } } } catch (IOException e) { context.processMessage(new CompilerMessage(getPresentableName(), e)); break; } } // registering generated files final Map<File, File[]> fsCache = FileCollectionFactory.createCanonicalFileMap(); for (ModuleBuildTarget target : targetsProcessed) { final Collection<ClassItem> items = remoteClasses.get(target); for (ClassItem item : items) { File[] children = fsCache.get(item.parentDir); if (children == null) { children = item.parentDir.listFiles(); if (children == null) { children = EMPTY_FILE_ARRAY; } fsCache.put(item.parentDir, children); } final Collection<File> files = item.selectGeneratedFiles(children); if (!files.isEmpty()) { final Collection<String> sources = item.compiledClass.getSourceFilesPaths(); for (File generated : files) { try { outputConsumer.registerOutputFile(target, generated, sources); } catch (IOException e) { context.processMessage(new CompilerMessage(getPresentableName(), e)); } } } } } return exitCode; }