support configscript in groovy compilation (IDEA-103342)
[idea/community.git] / plugins / groovy / jps-plugin / src / org / jetbrains / jps / incremental / groovy / ForkedGroovyc.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.jps.incremental.groovy;
17
18 import com.intellij.execution.process.BaseOSProcessHandler;
19 import com.intellij.execution.process.ProcessHandler;
20 import com.intellij.openapi.util.Key;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.util.ArrayUtil;
23 import com.intellij.util.Function;
24 import com.intellij.util.SystemProperties;
25 import com.intellij.util.containers.ContainerUtilRt;
26 import com.intellij.util.lang.UrlClassLoader;
27 import gnu.trove.THashMap;
28 import org.jetbrains.groovy.compiler.rt.GroovyRtConstants;
29 import org.jetbrains.jps.ModuleChunk;
30 import org.jetbrains.jps.cmdline.ClasspathBootstrap;
31 import org.jetbrains.jps.incremental.ExternalProcessUtil;
32 import org.jetbrains.jps.model.java.JpsJavaSdkType;
33 import org.jetbrains.jps.model.library.sdk.JpsSdk;
34 import org.jetbrains.jps.service.SharedThreadPool;
35
36 import java.io.File;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.concurrent.Future;
42
43 /**
44  * @author peter
45  */
46 class ForkedGroovyc implements GroovycFlavor {
47   private final boolean myOptimizeClassLoading;
48   private final ModuleChunk myChunk;
49
50   ForkedGroovyc(boolean optimizeClassLoading, ModuleChunk chunk) {
51     myOptimizeClassLoading = optimizeClassLoading;
52     myChunk = chunk;
53   }
54
55   @Override
56   public GroovycContinuation runGroovyc(Collection<String> compilationClassPath,
57                                         boolean forStubs,
58                                         JpsGroovySettings settings,
59                                         File tempFile,
60                                         final GroovycOutputParser parser)
61     throws Exception {
62     List<String> classpath = new ArrayList<String>();
63     if (myOptimizeClassLoading) {
64       classpath.addAll(GroovyBuilder.getGroovyRtRoots());
65       classpath.add(ClasspathBootstrap.getResourcePath(Function.class));
66       classpath.add(ClasspathBootstrap.getResourcePath(UrlClassLoader.class));
67       classpath.add(ClasspathBootstrap.getResourceFile(THashMap.class).getPath());
68     } else {
69       classpath.addAll(compilationClassPath);
70     }
71
72     List<String> vmParams = ContainerUtilRt.newArrayList();
73     vmParams.add("-Xmx" + System.getProperty("groovyc.heap.size", settings.heapSize) + "m");
74     vmParams.add("-Dfile.encoding=" + System.getProperty("file.encoding"));
75     //vmParams.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239");
76     
77     if ("false".equals(System.getProperty(GroovyRtConstants.GROOVYC_ASM_RESOLVING_ONLY))) {
78       vmParams.add("-D" + GroovyRtConstants.GROOVYC_ASM_RESOLVING_ONLY + "=false");
79     }
80     String configScript = settings.configScript;
81     if (StringUtil.isNotEmpty(configScript)) {
82       vmParams.add("-D" + GroovyRtConstants.GROOVYC_CONFIG_SCRIPT + "=" + configScript);
83     }
84
85     String grapeRoot = System.getProperty(GroovycOutputParser.GRAPE_ROOT);
86     if (grapeRoot != null) {
87       vmParams.add("-D" + GroovycOutputParser.GRAPE_ROOT + "=" + grapeRoot);
88     }
89
90     final List<String> cmd = ExternalProcessUtil.buildJavaCommandLine(
91       getJavaExecutable(myChunk),
92       "org.jetbrains.groovy.compiler.rt.GroovycRunner",
93       Collections.<String>emptyList(), classpath,
94       vmParams,
95       getProgramParams(tempFile, settings, forStubs)
96     );
97     final Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(cmd));
98     ProcessHandler handler = new BaseOSProcessHandler(process, null, null) {
99       @Override
100       protected Future<?> executeOnPooledThread(Runnable task) {
101         return SharedThreadPool.getInstance().executeOnPooledThread(task);
102       }
103
104       @Override
105       public void notifyTextAvailable(String text, Key outputType) {
106         parser.notifyTextAvailable(text, outputType);
107       }
108     };
109
110     handler.startNotify();
111     handler.waitFor();
112     parser.notifyFinished(process.exitValue());
113     return null;
114   }
115
116   private List<String> getProgramParams(File tempFile, JpsGroovySettings settings, boolean forStubs) {
117     List<String> programParams = ContainerUtilRt.newArrayList(myOptimizeClassLoading ? GroovyRtConstants.OPTIMIZE : "do_not_optimize",
118                                                               forStubs ? "stubs" : "groovyc",
119                                                               tempFile.getPath());
120     if (settings.invokeDynamic) {
121       programParams.add("--indy");
122     }
123     return programParams;
124   }
125
126
127   private static String getJavaExecutable(ModuleChunk chunk) {
128     JpsSdk<?> sdk = GroovyBuilder.getJdk(chunk);
129     return sdk != null ? JpsJavaSdkType.getJavaExecutable(sdk) : SystemProperties.getJavaHome() + "/bin/java";
130   }
131
132 }