private static CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings buildGlobalSettings() { final Map<String, String> data = new HashMap<String, String>(); for (Map.Entry<String, String> entry : PathMacrosImpl.getGlobalSystemMacros().entrySet()) { data.put(entry.getKey(), FileUtil.toSystemIndependentName(entry.getValue())); } final PathMacros pathVars = PathMacros.getInstance(); for (String name : pathVars.getAllMacroNames()) { final String path = pathVars.getValue(name); if (path != null) { data.put(name, FileUtil.toSystemIndependentName(path)); } } final List<GlobalLibrary> globals = new ArrayList<GlobalLibrary>(); fillSdks(globals); fillGlobalLibraries(globals); final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.Builder cmdBuilder = CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder(); if (!data.isEmpty()) { for (Map.Entry<String, String> entry : data.entrySet()) { final String var = entry.getKey(); final String value = entry.getValue(); if (var != null && value != null) { cmdBuilder.addPathVariable(CmdlineProtoUtil.createPair(var, value)); } } } if (!globals.isEmpty()) { for (GlobalLibrary lib : globals) { final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.GlobalLibrary.Builder libBuilder = CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.GlobalLibrary .newBuilder(); libBuilder.setName(lib.getName()).addAllPath(lib.getPaths()); if (lib instanceof SdkLibrary) { final SdkLibrary sdk = (SdkLibrary) lib; libBuilder.setHomePath(sdk.getHomePath()); libBuilder.setTypeName(sdk.getTypeName()); final String additional = sdk.getAdditionalDataXml(); if (additional != null) { libBuilder.setAdditionalDataXml(additional); } final String version = sdk.getVersion(); if (version != null) { libBuilder.setVersion(version); } } cmdBuilder.addGlobalLibrary(libBuilder.build()); } } final String defaultCharset = EncodingManager.getInstance().getDefaultCharsetName(); if (defaultCharset != null) { cmdBuilder.setGlobalEncoding(defaultCharset); } final String ignoredFilesList = FileTypeManager.getInstance().getIgnoredFilesList(); cmdBuilder.setIgnoredFilesPatterns(ignoredFilesList); return cmdBuilder.build(); }
@Nullable public RequestFuture scheduleBuild( final Project project, final boolean isRebuild, final boolean isMake, final Collection<String> modules, final Collection<String> artifacts, final Collection<String> paths, final Map<String, String> userData, DefaultMessageHandler handler) { final String projectPath = getProjectPath(project); final UUID sessionId = UUID.randomUUID(); final CmdlineRemoteProto.Message.ControllerMessage params; CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = myGlobals; if (globals == null) { globals = buildGlobalSettings(); myGlobals = globals; } CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges = null; final SequentialTaskExecutor projectTaskQueue; synchronized (myProjectDataMap) { ProjectData data = myProjectDataMap.get(projectPath); if (data == null) { data = new ProjectData(new SequentialTaskExecutor(myPooledThreadExecutor)); myProjectDataMap.put(projectPath, data); } if (isRebuild) { data.dropChanges(); } currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent(); projectTaskQueue = data.taskQueue; } if (isRebuild) { params = CmdlineProtoUtil.createRebuildRequest(projectPath, userData, globals); } else { params = isMake ? CmdlineProtoUtil.createMakeRequest( projectPath, modules, artifacts, userData, globals, currentFSChanges) : CmdlineProtoUtil.createForceCompileRequest( projectPath, modules, artifacts, paths, userData, globals, currentFSChanges); } myMessageDispatcher.registerBuildMessageHandler(sessionId, handler, params); // ensure server is listening if (myListenPort < 0) { try { myListenPort = startListening(); } catch (Exception e) { myMessageDispatcher.unregisterBuildMessageHandler(sessionId); handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null)); handler.sessionTerminated(); return null; } } final RequestFuture<BuilderMessageHandler> future = new RequestFuture<BuilderMessageHandler>( handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() { @Override public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception { myMessageDispatcher.cancelSession(future.getRequestID()); } }); projectTaskQueue.submit( new Runnable() { @Override public void run() { try { if (project.isDisposed()) { future.cancel(false); return; } myBuildsInProgress.put(projectPath, future); final Process process = launchBuildProcess(project, myListenPort, sessionId); final OSProcessHandler processHandler = new OSProcessHandler(process, null) { @Override protected boolean shouldDestroyProcessRecursively() { return true; } }; final StringBuilder stdErrOutput = new StringBuilder(); processHandler.addProcessListener( new ProcessAdapter() { @Override public void processTerminated(ProcessEvent event) { final BuilderMessageHandler handler = myMessageDispatcher.unregisterBuildMessageHandler(sessionId); if (handler != null) { handler.sessionTerminated(); } } @Override public void onTextAvailable(ProcessEvent event, Key outputType) { // re-translate builder's output to idea.log final String text = event.getText(); if (!StringUtil.isEmpty(text)) { LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim()); if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) { stdErrOutput.append(text); } } } }); processHandler.startNotify(); final boolean terminated = processHandler.waitFor(); if (terminated) { final int exitValue = processHandler.getProcess().exitValue(); if (exitValue != 0) { final StringBuilder msg = new StringBuilder(); msg.append("Abnormal build process termination: "); if (stdErrOutput.length() > 0) { msg.append("\n").append(stdErrOutput); } else { msg.append("unknown error"); } future .getMessageHandler() .handleFailure( sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null)); } } else { future .getMessageHandler() .handleFailure( sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null)); } } catch (ExecutionException e) { myMessageDispatcher.unregisterBuildMessageHandler(sessionId); future .getMessageHandler() .handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e)); future.getMessageHandler().sessionTerminated(); } finally { myBuildsInProgress.remove(projectPath); future.setDone(); } } }); return future; }