cdd778e32ff167afcd7e8fc51296a796b087f207
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / javac / JavacServerBootstrap.java
1 package org.jetbrains.jps.javac;
2
3 import com.intellij.execution.process.BaseOSProcessHandler;
4 import com.intellij.execution.process.ProcessAdapter;
5 import com.intellij.execution.process.ProcessEvent;
6 import com.intellij.execution.process.ProcessOutputTypes;
7 import com.intellij.openapi.util.Key;
8 import com.intellij.openapi.util.Ref;
9 import com.intellij.openapi.util.SystemInfo;
10 import com.intellij.openapi.util.io.FileUtil;
11 import com.intellij.openapi.util.text.StringUtil;
12 import com.intellij.util.concurrency.Semaphore;
13 import org.jetbrains.jps.server.ClasspathBootstrap;
14
15 import java.io.File;
16 import java.util.ArrayList;
17 import java.util.List;
18
19 /**
20  * @author Eugene Zhuravlev
21  *         Date: 1/24/12
22  */
23 public class JavacServerBootstrap {
24
25   public static BaseOSProcessHandler launchJavacServer(String vmExecutablePath,
26                                                        int heapSize,
27                                                        int port,
28                                                        File workingDir,
29                                                        List<String> vmOptions) throws Exception {
30
31     final List<String> cmdLine = new ArrayList<String>();
32     appendParam(cmdLine, vmExecutablePath);
33     appendParam(cmdLine, "-server");
34     appendParam(cmdLine, "-XX:MaxPermSize=150m");
35     //appendParam(cmdLine, "-XX:ReservedCodeCacheSize=64m");
36     appendParam(cmdLine, "-Djava.awt.headless=true");
37     appendParam(cmdLine, "-Xmx" + heapSize + "m");
38
39     // debugging
40     //appendParam(cmdLine, "-XX:+HeapDumpOnOutOfMemoryError");
41     //appendParam(cmdLine, "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5009");
42
43     // javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language
44     final String lang = System.getProperty("user.language");
45     if (lang != null) {
46       //noinspection HardCodedStringLiteral
47       appendParam(cmdLine, "-Duser.language=" + lang);
48     }
49     final String country = System.getProperty("user.country");
50     if (country != null) {
51       //noinspection HardCodedStringLiteral
52       appendParam(cmdLine, "-Duser.country=" + country);
53     }
54     //noinspection HardCodedStringLiteral
55     final String region = System.getProperty("user.region");
56     if (region != null) {
57       //noinspection HardCodedStringLiteral
58       appendParam(cmdLine, "-Duser.region=" + region);
59     }
60
61     for (String option : vmOptions) {
62       appendParam(cmdLine, option);
63     }
64
65     appendParam(cmdLine, "-classpath");
66
67     final List<File> cp = ClasspathBootstrap.getJavacServerClasspath();
68     final StringBuilder classpath = new StringBuilder();
69     for (File file : cp) {
70       if (classpath.length() > 0) {
71         classpath.append(File.pathSeparator);
72       }
73       classpath.append(file.getPath());
74     }
75     appendParam(cmdLine, classpath.toString());
76
77     appendParam(cmdLine, org.jetbrains.jps.javac.JavacServer.class.getName());
78     appendParam(cmdLine, Integer.toString(port));
79
80     workingDir.mkdirs();
81
82     appendParam(cmdLine, FileUtil.toSystemIndependentName(workingDir.getPath()));
83
84     final ProcessBuilder builder = new ProcessBuilder(cmdLine);
85     builder.directory(workingDir);
86
87     final Process process = builder.start();
88     final BaseOSProcessHandler processHandler = new BaseOSProcessHandler(process, null, null);
89     configureProcessHandler(processHandler);
90
91     return processHandler;
92   }
93
94   private static void configureProcessHandler(final BaseOSProcessHandler processHandler) throws Exception {
95     processHandler.addProcessListener(new ProcessAdapter() {
96       public void onTextAvailable(ProcessEvent event, Key outputType) {
97         final String text = event.getText();
98         if (text != null && text.length() > 0) {
99           System.out.print("JAVAC_SERVER [" + outputType.toString() + "]: " + text);
100         }
101       }
102     });
103     final Semaphore semaphore  = new Semaphore();
104     semaphore.down();
105     final Ref<String> serverStartMessage = new Ref<String>(null);
106     processHandler.addProcessListener(new ProcessAdapter() {
107       public void processTerminated(ProcessEvent event) {
108         try {
109           processHandler.removeProcessListener(this);
110         }
111         finally {
112           semaphore.up();
113         }
114       }
115
116       public void onTextAvailable(ProcessEvent event, Key outputType) {
117         if (outputType == ProcessOutputTypes.STDERR) {
118           try {
119             final String text = event.getText();
120             if (text != null) {
121               if (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE)) {
122                 processHandler.removeProcessListener(this);
123                 serverStartMessage.set(text);
124               }
125             }
126           }
127           finally {
128             semaphore.up();
129           }
130         }
131       }
132     });
133     processHandler.startNotify();
134     semaphore.waitFor();
135
136     final String startupMsg = serverStartMessage.get();
137     if (startupMsg == null || !startupMsg.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE)) {
138       throw new Exception("Server startup failed: " + startupMsg);
139     }
140   }
141
142   private static void appendParam(List<String> cmdLine, String param) {
143     if (SystemInfo.isWindows) {
144       if (param.contains("\"")) {
145         param = StringUtil.replace(param, "\"", "\\\"");
146       }
147       else if (param.length() == 0) {
148         param = "\"\"";
149       }
150     }
151     cmdLine.add(param);
152   }
153 }