/*
* Copyright 2010-2015 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.kotlin.compilerRunner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils;
import org.jetbrains.kotlin.preloading.Preloader;
import org.jetbrains.kotlin.utils.KotlinPaths;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.util.Collections;
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
public class CompilerRunnerUtil {
private static SoftReference<ClassLoader> ourClassLoaderRef = new SoftReference<ClassLoader>(null);
@NotNull
private static synchronized ClassLoader getOrCreateClassLoader(
@NotNull JpsCompilerEnvironment environment,
@NotNull File libPath
) throws IOException {
ClassLoader classLoader = ourClassLoaderRef.get();
if (classLoader == null) {
classLoader = ClassPreloadingUtils.preloadClasses(
Collections.singletonList(new File(libPath, "kotlin-compiler.jar")),
Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
CompilerRunnerUtil.class.getClassLoader(),
environment.getClassesToLoadByParent()
);
ourClassLoaderRef = new SoftReference<ClassLoader>(classLoader);
}
return classLoader;
}
@Nullable
public static File getLibPath(@NotNull KotlinPaths paths, @NotNull MessageCollector messageCollector) {
File libs = paths.getLibPath();
if (libs.exists() && !libs.isFile()) return libs;
messageCollector.report(
ERROR,
"Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed",
null
);
return null;
}
@Nullable
public static Object invokeExecMethod(
@NotNull String compilerClassName,
@NotNull String[] arguments,
@NotNull JpsCompilerEnvironment environment,
@NotNull PrintStream out
) throws Exception {
File libPath = getLibPath(environment.getKotlinPaths(), environment.getMessageCollector());
if (libPath == null) return null;
ClassLoader classLoader = getOrCreateClassLoader(environment, libPath);
Class<?> kompiler = Class.forName(compilerClassName, true, classLoader);
Method exec = kompiler.getMethod(
"execAndOutputXml",
PrintStream.class,
Class.forName("org.jetbrains.kotlin.config.Services", true, classLoader),
String[].class
);
return exec.invoke(kompiler.newInstance(), out, environment.getServices(), arguments);
}
}