From de94d5c4144fa4922aad781708f2323ad6d37c5b Mon Sep 17 00:00:00 2001 From: Yaroslav Ulanovych Date: Sun, 17 Apr 2016 18:06:38 +0300 Subject: [PATCH] Fix KT-11839 maven goal to execute kotlin script --- .../tools/kotlin-maven-plugin-test/pom.xml | 5 +- .../pom.xml | 47 +++ .../script.kts | 5 + .../verify.bsh | 3 + .../invoker.properties | 1 + .../pom.xml | 47 +++ .../verify.bsh | 4 + .../it/test-executeKotlinScriptFile/pom.xml | 47 +++ .../test-executeKotlinScriptFile/script.kts | 1 + .../test-executeKotlinScriptFile/verify.bsh | 3 + .../it/test-executeKotlinScriptInline/pom.xml | 47 +++ .../test-executeKotlinScriptInline/verify.bsh | 3 + .../invoker.properties | 1 + .../pom.xml | 47 +++ .../verify.bsh | 4 + .../verify-common.bsh | 37 +++ .../kotlin/maven/ExecuteKotlinScriptMojo.java | 286 ++++++++++++++++++ .../kotlin/maven/K2JVMCompileMojo.java | 12 +- .../kotlin/maven/KotlinCompileMojoBase.java | 20 +- .../maven/MavenPluginLogMessageCollector.java | 49 +++ .../maven/ScriptExecutionException.java | 32 ++ .../java/org/jetbrains/kotlin/maven/Util.java | 34 +++ 22 files changed, 704 insertions(+), 31 deletions(-) create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/pom.xml create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/script.kts create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/verify.bsh create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/invoker.properties create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/pom.xml create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/verify.bsh create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/pom.xml create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/script.kts create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/verify.bsh create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/pom.xml create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/verify.bsh create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/invoker.properties create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/pom.xml create mode 100644 libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/verify.bsh create mode 100644 libraries/tools/kotlin-maven-plugin-test/verify-common.bsh create mode 100644 libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java create mode 100644 libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java create mode 100644 libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ScriptExecutionException.java create mode 100644 libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/Util.java diff --git a/libraries/tools/kotlin-maven-plugin-test/pom.xml b/libraries/tools/kotlin-maven-plugin-test/pom.xml index e78627fb7ec..4fb10b38029 100644 --- a/libraries/tools/kotlin-maven-plugin-test/pom.xml +++ b/libraries/tools/kotlin-maven-plugin-test/pom.xml @@ -54,8 +54,9 @@ local-repo - verify.bsh - true + verify + false + invoker.properties diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/pom.xml new file mode 100644 index 00000000000..fd7da9c468c --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + test-executeKotlinScriptBuildAccess + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + execute-kotlin-script + compile + + script + + + script.kts + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/script.kts b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/script.kts new file mode 100644 index 00000000000..ec39b28cc26 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/script.kts @@ -0,0 +1,5 @@ +import org.jetbrains.kotlin.maven.ExecuteKotlinScriptMojo + +val mojo = ExecuteKotlinScriptMojo.INSTANCE + +mojo.getLog().info("kotlin build script accessing build info of ${mojo.project.artifactId} project") \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/verify.bsh new file mode 100644 index 00000000000..78cece6e61a --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptBuildAccess/verify.bsh @@ -0,0 +1,3 @@ +source("verify-common.bsh"); + +assertBuildLogHasLine("[INFO] kotlin build script accessing build info of test-executeKotlinScriptBuildAccess project") \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/invoker.properties b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/invoker.properties new file mode 100644 index 00000000000..62359c56d4b --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/invoker.properties @@ -0,0 +1 @@ +invoker.buildResult = failure \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/pom.xml new file mode 100644 index 00000000000..b3d4f18ac2f --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + test-executeKotlinScriptCompileError + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + execute-kotlin-script + compile + + script + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/verify.bsh new file mode 100644 index 00000000000..e4fe18ea53a --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptCompileError/verify.bsh @@ -0,0 +1,4 @@ +source("verify-common.bsh"); + +assertBuildLogHasLine("[INFO] BUILD FAILURE"); +assertBuildLogHasLineThatContains("Unresolved reference: compileErrorHere"); \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/pom.xml new file mode 100644 index 00000000000..1f606cbcb1a --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + test-executeKotlinScriptFile + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + execute-kotlin-script + compile + + script + + + script.kts + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/script.kts b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/script.kts new file mode 100644 index 00000000000..fa5095a59f1 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/script.kts @@ -0,0 +1 @@ +println("Hello from Kotlin script file!") \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/verify.bsh new file mode 100644 index 00000000000..8a8264740fa --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptFile/verify.bsh @@ -0,0 +1,3 @@ +source("verify-common.bsh"); + +assertBuildLogHasLine("Hello from Kotlin script file!") \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/pom.xml new file mode 100644 index 00000000000..d51388e34b0 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + test-executeKotlinScriptInline + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + execute-kotlin-script + compile + + script + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/verify.bsh new file mode 100644 index 00000000000..a6b9011a50c --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptInline/verify.bsh @@ -0,0 +1,3 @@ +source("verify-common.bsh"); + +assertBuildLogHasLine("Hello from inline Kotlin script!") \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/invoker.properties b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/invoker.properties new file mode 100644 index 00000000000..62359c56d4b --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/invoker.properties @@ -0,0 +1 @@ +invoker.buildResult = failure \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/pom.xml new file mode 100644 index 00000000000..6cf0c623dbd --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + test-executeKotlinScriptScriptException + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + execute-kotlin-script + compile + + script + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/verify.bsh new file mode 100644 index 00000000000..72ac6fab331 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-executeKotlinScriptScriptException/verify.bsh @@ -0,0 +1,4 @@ +source("verify-common.bsh"); + +assertBuildLogHasLine("[INFO] BUILD FAILURE"); +assertBuildLogHasLineThatContains("script threw an exception: exception from script"); \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/verify-common.bsh b/libraries/tools/kotlin-maven-plugin-test/verify-common.bsh new file mode 100644 index 00000000000..79ee150bfbe --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/verify-common.bsh @@ -0,0 +1,37 @@ +File buildLog = new File(basedir, "build.log"); + +void assertBuildLogHasLine(String expectedLine) { + BufferedReader reader = new BufferedReader(new FileReader(buildLog)); + try { + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + i++; + if (line.equals(expectedLine)) { + print("Expected line was found at line " + i + " of build log: " + "\"" + expectedLine + "\""); + return; + } + } + throw new Exception("Expected build log to contain line: \"" + expectedLine + "\""); + } finally { + reader.close(); + } +} + +void assertBuildLogHasLineThatContains(String content) { + BufferedReader reader = new BufferedReader(new FileReader(buildLog)); + try { + String line; + int i = 0; + while ((line = reader.readLine()) != null) { + i++; + if (line.contains(content)) { + print("Expected content " + "\"" + content + "\"" + " was found at line " + i + " of build log: " + "\"" + line + "\""); + return; + } + } + throw new Exception("Expected build log to contain: \"" + content + "\""); + } finally { + reader.close(); + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java new file mode 100644 index 00000000000..7c3595a69d8 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java @@ -0,0 +1,286 @@ +/* + * Copyright 2010-2016 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.maven; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; +import org.jetbrains.kotlin.cli.common.messages.MessageSeverityCollector; +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler; +import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys; +import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot; +import org.jetbrains.kotlin.codegen.GeneratedClassLoader; +import org.jetbrains.kotlin.codegen.state.GenerationState; +import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback; +import org.jetbrains.kotlin.config.CommonConfigurationKeys; +import org.jetbrains.kotlin.config.CompilerConfiguration; +import org.jetbrains.kotlin.config.KotlinSourceRoot; +import org.jetbrains.kotlin.load.java.JvmAbi; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.psi.KtScript; +import org.jetbrains.kotlin.script.StandardScriptDefinition; +import org.jetbrains.kotlin.utils.PathUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** + * Allows to execute kotlin script files during the build process. + * You can specify script file or inline script to be executed. + *
+ * Scripts have access to the build information. + * When compiling, kotlin maven plugin jar and it's dependencies + * (including core maven libraries) are added to classpath. + * Before execution this mojo is exposed to the script via static variable + * and maven project is stored in mojo's project field for script access. + *
+ *

+ *     import org.jetbrains.kotlin.maven.ExecuteKotlinScriptMojo
+ *     val mojo = ExecuteKotlinScriptMojo.INSTANCE
+ *     mojo.getLog().info("kotlin build script accessing build info of ${mojo.project.artifactId} project")
+ * 
+ */ +@Mojo(name = "script", requiresDependencyResolution = ResolutionScope.COMPILE) +public class ExecuteKotlinScriptMojo extends AbstractMojo { + /** + * The Kotlin script file to be executed. + * Either this or {@code script} parameter must be specified. + */ + @Parameter + private File scriptFile; + + /** + * The inline Kotlin script to be executed. + * Either this or {@code scriptFile} parameter must be specified. + */ + @Parameter + private String script; + + /** + * The content of inline scripts is temporarily stored here. + */ + @Parameter(defaultValue = "${project.build.directory}/kotlin-build-scripts", required = true) + private File buildDirectory; + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + public MavenProject project; + + @Parameter(defaultValue = "${plugin}", required = true, readonly = true) + private PluginDescriptor plugin; + + @Parameter(defaultValue = "${localRepository}", required = true, readonly = true) + private ArtifactRepository localRepository; + + @Component + private ArtifactHandlerManager artifactHandlerManager; + + public static ExecuteKotlinScriptMojo INSTANCE; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + if (scriptFile != null && script == null) { + executeScriptFile(scriptFile); + } else if (scriptFile == null && script != null) { + executeScriptInline(); + } else { + throw new MojoExecutionException("Either scriptFile or script parameter must be specified"); + } + } + + private void executeScriptInline() throws MojoExecutionException { + try { + if (!buildDirectory.exists()) { + buildDirectory.mkdirs(); + } + + File scriptFile = File.createTempFile("kotlin-maven-plugin-inline-script-", ".tmp.kts", buildDirectory); + FileOutputStream stream = new FileOutputStream(scriptFile); + stream.write(script.getBytes("UTF-8")); + stream.close(); + + try { + executeScriptFile(scriptFile); + } finally { + boolean deleted = scriptFile.delete(); + if (!deleted) { + getLog().warn("Error deleting " + scriptFile.getAbsolutePath()); + } + } + } catch (IOException e) { + throw new MojoExecutionException("Error executing inline script", e); + } + } + + private void executeScriptFile(File scriptFile) throws MojoExecutionException { + initCompiler(); + + Disposable rootDisposable = Disposer.newDisposable(); + + try { + MavenPluginLogMessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); + + CompilerConfiguration configuration = new CompilerConfiguration(); + + configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, new MessageSeverityCollector(messageCollector)); + + List deps = new ArrayList(); + + deps.addAll(PathUtil.getJdkClassesRoots()); + deps.addAll(getDependenciesForScript()); + + for (File item: deps) { + if (item.exists()) { + configuration.add(CommonConfigurationKeys.CONTENT_ROOTS, new JvmClasspathRoot(item)); + getLog().debug("Adding to classpath: " + item.getAbsolutePath()); + } else { + getLog().debug("Skipping non-existing dependency: " + item.getAbsolutePath()); + } + } + + configuration.add(CommonConfigurationKeys.CONTENT_ROOTS, new KotlinSourceRoot(scriptFile.getAbsolutePath())); + configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME); + configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition.INSTANCE); + + KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); + + GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(environment, GenerationStateEventCallback.Companion.getDO_NOTHING()); + + if (state == null) { + throw new ScriptExecutionException(scriptFile, "compile error"); + } + + GeneratedClassLoader classLoader = new GeneratedClassLoader(state.getFactory(), getClass().getClassLoader()); + KtScript script = environment.getSourceFiles().get(0).getScript(); + FqName nameForScript = script.getFqName(); + + try { + Class klass = classLoader.loadClass(nameForScript.asString()); + Constructor constructor = klass.getConstructor(String[].class); + ExecuteKotlinScriptMojo.INSTANCE = this; + constructor.newInstance(new Object[]{new String[]{}}); + } catch (InstantiationException e) { + throw new ScriptExecutionException(scriptFile, "internal error", e); + } catch (InvocationTargetException e) { + throw new ScriptExecutionException(scriptFile, "script threw an exception", e.getCause()); + } catch (NoSuchMethodException e) { + throw new ScriptExecutionException(scriptFile, "internal error", e); + } catch (IllegalAccessException e) { + throw new ScriptExecutionException(scriptFile, "internal error", e); + } catch (ClassNotFoundException e) { + throw new ScriptExecutionException(scriptFile, "internal error", e); + } + } + finally { + rootDisposable.dispose(); + ExecuteKotlinScriptMojo.INSTANCE = null; + } + } + + private List getDependenciesForScript() throws MojoExecutionException { + List deps = new ArrayList(); + + deps.add(getKotlinStdlibDependency()); + deps.add(getThisPluginAsDependency()); + + deps.addAll(getThisPluginDependencies()); + + return deps; + } + + private File getDependencyFile(ComponentDependency dep) { + ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler(dep.getType()); + Artifact artifact = new DefaultArtifact(dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), null, dep.getType(), null, artifactHandler); + localRepository.find(artifact); + return artifact.getFile(); + } + + private File getDependencyFile(Dependency dep) { + ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler(dep.getType()); + Artifact artifact = new DefaultArtifact(dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), null, dep.getType(), null, artifactHandler); + localRepository.find(artifact); + return artifact.getFile(); + } + + private List getThisPluginDependencies() { + List files = new ArrayList(); + + for (ComponentDependency dep: plugin.getDependencies()) { + files.add(getDependencyFile(dep)); + } + + return files; + } + + private File getThisPluginAsDependency() { + ComponentDependency dep = new ComponentDependency(); + + dep.setGroupId(plugin.getGroupId()); + dep.setArtifactId(plugin.getArtifactId()); + dep.setVersion(plugin.getVersion()); + + return getDependencyFile(dep); + } + + private File getKotlinStdlibDependency() throws MojoExecutionException { + Dependency result = null; + + for (Dependency dep: project.getDependencies()) { + if (dep.getArtifactId().equals("kotlin-stdlib")) { + result = dep; + break; + } + } + + if (result == null) { + throw new MojoExecutionException("Unable to find Kotlin standard library among project dependencies"); + } + + return getDependencyFile(result); + } + + private void initCompiler() { + // execute static init of CLICompiler, had warnings without it + // WARN: Failed to initialize native filesystem for Windows + // java.lang.RuntimeException: Could not find installation home path. Please make sure bin/idea.properties is present in the installation directory. + // at com.intellij.openapi.application.PathManager.getHomePath(PathManager.java:96) + new K2JVMCompiler(); + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/K2JVMCompileMojo.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/K2JVMCompileMojo.java index 172c556ba88..47927f22ba1 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/K2JVMCompileMojo.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/K2JVMCompileMojo.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.List; import static com.intellij.openapi.util.text.StringUtil.join; +import static org.jetbrains.kotlin.maven.Util.filterClassPath; /** * Compiles kotlin sources @@ -84,7 +85,7 @@ public class K2JVMCompileMojo extends KotlinCompileMojoBase classpathList = filterClassPath(classpath); + List classpathList = filterClassPath(project.getBasedir(), classpath); if (!classpathList.isEmpty()) { String classPathString = join(classpathList, File.pathSeparator); @@ -102,13 +103,4 @@ public class K2JVMCompileMojo extends KotlinCompileMojoBase filterClassPath(List classpath) { - return CollectionsKt.filter(classpath, new Function1() { - @Override - public Boolean invoke(String s) { - return new File(s).exists() || new File(project.getBasedir(), s).exists(); - } - }); - } } diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java index 2bb69c1065f..27a985a2670 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java @@ -119,25 +119,7 @@ public abstract class KotlinCompileMojoBase e configureCompilerArguments(arguments, compiler); printCompilerArgumentsIfDebugEnabled(arguments, compiler); - MessageCollector messageCollector = new MessageCollector() { - @Override - public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) { - String path = location.getPath(); - String position = path == null ? "" : path + ": (" + (location.getLine() + ", " + location.getColumn()) + ") "; - - String text = position + message; - - if (CompilerMessageSeverity.VERBOSE.contains(severity)) { - getLog().debug(text); - } else if (CompilerMessageSeverity.ERRORS.contains(severity)) { - getLog().error(text); - } else if (severity == CompilerMessageSeverity.INFO) { - getLog().info(text); - } else { - getLog().warn(text); - } - } - }; + MessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); ExitCode exitCode = executeCompiler(compiler, arguments, messageCollector); diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java new file mode 100644 index 00000000000..a40703507ef --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2016 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.maven; + +import org.apache.maven.plugin.logging.Log; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; +import org.jetbrains.kotlin.cli.common.messages.MessageCollector; + +public class MavenPluginLogMessageCollector implements MessageCollector { + private final Log log; + + public MavenPluginLogMessageCollector(Log log) { + this.log = log; + } + + @Override + public void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location) { + String path = location.getPath(); + String position = path == null ? "" : path + ": (" + (location.getLine() + ", " + location.getColumn()) + ") "; + + String text = position + message; + + if (CompilerMessageSeverity.VERBOSE.contains(severity)) { + log.debug(text); + } else if (CompilerMessageSeverity.ERRORS.contains(severity)) { + log.error(text); + } else if (severity == CompilerMessageSeverity.INFO) { + log.info(text); + } else { + log.warn(text); + } + } +} diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ScriptExecutionException.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ScriptExecutionException.java new file mode 100644 index 00000000000..e4f2fd4f6b2 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ScriptExecutionException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2016 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.maven; + +import org.apache.maven.plugin.MojoExecutionException; + +import java.io.File; + +public class ScriptExecutionException extends MojoExecutionException { + public ScriptExecutionException(File script, String msg) { + super("Error executing script " + script.getAbsolutePath() + ": " + msg); + } + + public ScriptExecutionException(File script, String msg, Throwable cause) { + super("Error executing script " + script.getAbsolutePath() + ": " + msg, cause); + } +} diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/Util.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/Util.java new file mode 100644 index 00000000000..6d2b2543bfb --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/Util.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2016 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.maven; + +import kotlin.collections.CollectionsKt; +import kotlin.jvm.functions.Function1; + +import java.io.File; +import java.util.List; + +public class Util { + static List filterClassPath(final File basedir, List classpath) { + return CollectionsKt.filter(classpath, new Function1() { + @Override + public Boolean invoke(String s) { + return new File(s).exists() || new File(basedir, s).exists(); + } + }); + } +}