blob: ecf53395eb53318f241d2269fda6c43e0b0a96dd [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jps.javac;
import com.intellij.execution.process.BaseOSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.jps.builders.java.JavaCompilingTool;
import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
/**
* @author Eugene Zhuravlev
* Date: 1/24/12
*/
public class JavacServerBootstrap {
public static ExternalJavacProcessHandler launchExternalJavacProcess(UUID uuid, String sdkHomePath,
int heapSize,
int port,
File workingDir,
List<String> vmOptions,
JavaCompilingTool compilingTool) throws Exception {
final List<String> cmdLine = new ArrayList<String>();
appendParam(cmdLine, getVMExecutablePath(sdkHomePath));
//appendParam(cmdLine, "-XX:MaxPermSize=150m");
//appendParam(cmdLine, "-XX:ReservedCodeCacheSize=64m");
appendParam(cmdLine, "-Djava.awt.headless=true");
final int xms = heapSize / 2;
if (xms > 32) {
appendParam(cmdLine, "-Xms" + xms + "m");
}
appendParam(cmdLine, "-Xmx" + heapSize + "m");
// debugging
//appendParam(cmdLine, "-XX:+HeapDumpOnOutOfMemoryError");
//appendParam(cmdLine, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5009");
// javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language
final String encoding = System.getProperty("file.encoding");
if (encoding != null) {
appendParam(cmdLine, "-Dfile.encoding=" + encoding);
}
final String lang = System.getProperty("user.language");
if (lang != null) {
//noinspection HardCodedStringLiteral
appendParam(cmdLine, "-Duser.language=" + lang);
}
final String country = System.getProperty("user.country");
if (country != null) {
//noinspection HardCodedStringLiteral
appendParam(cmdLine, "-Duser.country=" + country);
}
//noinspection HardCodedStringLiteral
final String region = System.getProperty("user.region");
if (region != null) {
//noinspection HardCodedStringLiteral
appendParam(cmdLine, "-Duser.region=" + region);
}
appendParam(cmdLine, "-D" + ExternalJavacProcess.JPS_JAVA_COMPILING_TOOL_PROPERTY + "=" + compilingTool.getId());
// this will disable standard extensions to ensure javac is loaded from the right tools.jar
appendParam(cmdLine, "-Djava.ext.dirs=");
appendParam(cmdLine, "-Dlog4j.defaultInitOverride=true");
for (String option : vmOptions) {
appendParam(cmdLine, option);
}
appendParam(cmdLine, "-classpath");
final List<File> cp = ClasspathBootstrap.getExternalJavacProcessClasspath(sdkHomePath, compilingTool);
final StringBuilder classpath = new StringBuilder();
for (File file : cp) {
if (classpath.length() > 0) {
classpath.append(File.pathSeparator);
}
classpath.append(file.getPath());
}
appendParam(cmdLine, classpath.toString());
appendParam(cmdLine, org.jetbrains.jps.javac.ExternalJavacProcess.class.getName());
appendParam(cmdLine, uuid.toString());
appendParam(cmdLine, "127.0.0.1");
appendParam(cmdLine, Integer.toString(port));
workingDir.mkdirs();
appendParam(cmdLine, FileUtil.toSystemIndependentName(workingDir.getPath()));
final ProcessBuilder builder = new ProcessBuilder(cmdLine);
builder.directory(workingDir);
final Process process = builder.start();
final ExternalJavacProcessHandler processHandler = new ExternalJavacProcessHandler(process);
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
processHandler.setExitCode(event.getExitCode());
}
public void onTextAvailable(ProcessEvent event, Key outputType) {
final String text = event.getText();
if (!StringUtil.isEmptyOrSpaces(text)) {
if (outputType == ProcessOutputTypes.STDOUT) {
System.out.print("JAVAC_PROCESS: " + text);
}
else if (outputType == ProcessOutputTypes.STDERR) {
System.err.print("JAVAC_PROCESS: " + text);
}
}
}
});
processHandler.startNotify();
return processHandler;
}
private static void appendParam(List<String> cmdLine, String param) {
if (SystemInfo.isWindows) {
if (param.contains("\"")) {
param = StringUtil.replace(param, "\"", "\\\"");
}
else if (param.length() == 0) {
param = "\"\"";
}
}
cmdLine.add(param);
}
public static String getVMExecutablePath(String sdkHome) {
return sdkHome + "/bin/java";
}
public static class ExternalJavacProcessHandler extends BaseOSProcessHandler {
private volatile int myExitCode;
ExternalJavacProcessHandler(Process process) {
super(process, null, null);
}
@Override
protected Future<?> executeOnPooledThread(Runnable task) {
return SharedThreadPool.getInstance().executeOnPooledThread(task);
}
void setExitCode(int exitCode) {
myExitCode = exitCode;
}
public int getExitCode() {
return myExitCode;
}
}
}