From d4332bfb76672ced58c0836b868ec1376ba89146 Mon Sep 17 00:00:00 2001 From: "Muthuramalingam, Brinda Santh" Date: Fri, 25 Jan 2019 20:17:35 -0500 Subject: blueprint scripting module Change-Id: Ibe7602bdb6708d9adbe1aecd26eb14e24872f75d Issue-ID: CCSDK-941 Signed-off-by: Muthuramalingam, Brinda Santh --- .../core/script/BluePrintScriptConfiguration.kt | 86 ------------ .../core/script/BluePrintScriptService.kt | 78 ----------- .../core/script/BlueprintScriptingHost.kt | 93 ------------- .../core/script/BluePrintScriptServiceTest.kt | 49 ------- components/parent/pom.xml | 26 +--- ms/blueprintsprocessor/parent/pom.xml | 19 ++- .../src/main/resources/application.properties | 2 +- .../modules/blueprint-scripts/pom.xml | 59 ++++++++ .../scripts/BluePrintCompiledScript.kt | 56 ++++++++ .../scripts/BluePrintCompilerProxy.kt | 150 +++++++++++++++++++++ .../scripts/BluePrintScriptConfiguration.kt | 61 +++++++++ .../scripts/BlueprintScriptingHost.kt | 92 +++++++++++++ .../scripts/BlueprintScriptingHostTest.kt | 88 ++++++++++++ .../src/test/resources/scripts1/simple.cba.kts | 55 ++++++++ .../src/test/resources/scripts2/simple.cba.kts | 55 ++++++++ ms/controllerblueprints/modules/pom.xml | 1 + ms/controllerblueprints/modules/service/pom.xml | 6 +- ms/controllerblueprints/parent/pom.xml | 38 ++++-- 18 files changed, 664 insertions(+), 350 deletions(-) delete mode 100644 components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptConfiguration.kt delete mode 100644 components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptService.kt delete mode 100644 components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BlueprintScriptingHost.kt delete mode 100644 components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptServiceTest.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/pom.xml create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompiledScript.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompilerProxy.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintScriptConfiguration.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHost.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHostTest.kt create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts1/simple.cba.kts create mode 100644 ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts2/simple.cba.kts diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptConfiguration.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptConfiguration.kt deleted file mode 100644 index f7bfb857..00000000 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptConfiguration.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * 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.onap.ccsdk.apps.controllerblueprints.core.script - -import org.jetbrains.kotlin.script.util.LocalFilesResolver -import java.io.File -import kotlin.script.dependencies.ScriptContents -import kotlin.script.dependencies.ScriptDependenciesResolver -import kotlin.script.experimental.annotations.KotlinScript -import kotlin.script.experimental.api.* -import kotlin.script.experimental.jvm.JvmDependency -import kotlin.script.experimental.jvm.dependenciesFromCurrentContext -import kotlin.script.experimental.jvm.jvm - - -@KotlinScript(fileExtension = "kts", - compilationConfiguration = ComponentScriptConfiguration::class) -abstract class ComponentScript { - -} - -object ComponentScriptConfiguration : ScriptCompilationConfiguration( - { - // defaultImports(DependsOn::class, Repository::class) - jvm { - dependenciesFromCurrentContext( - wholeClasspath = true - ) - } -// refineConfiguration { -// onAnnotations(DependsOn::class, Repository::class, handler = ::configureLocalFileDepsOnAnnotations) -// } - } -) - - -private val resolver = LocalFilesResolver() - -fun configureLocalFileDepsOnAnnotations(context: ScriptConfigurationRefinementContext): - ResultWithDiagnostics { - - val annotations = context.collectedData?.get(ScriptCollectedData.foundAnnotations)?.takeIf { it.isNotEmpty() } - ?: return context.compilationConfiguration.asSuccess() - - val scriptContents = object : ScriptContents { - override val annotations: Iterable = annotations - override val file: File? = null - override val text: CharSequence? = null - } - - val diagnostics = arrayListOf() - - fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) { - //TODO - } - - return try { - val newDepsFromResolver = resolver.resolve(scriptContents, emptyMap(), ::report, null).get() - ?: return context.compilationConfiguration.asSuccess(diagnostics) - - val resolvedClasspath = newDepsFromResolver.classpath.toList().takeIf { it.isNotEmpty() } - ?: return context.compilationConfiguration.asSuccess(diagnostics) - - ScriptCompilationConfiguration(context.compilationConfiguration) { - dependencies.append(JvmDependency(resolvedClasspath)) - - }.asSuccess(diagnostics) - - } catch (e: Throwable) { - ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics()) - } -} \ No newline at end of file diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptService.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptService.kt deleted file mode 100644 index 8ae09151..00000000 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptService.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * 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.onap.ccsdk.apps.controllerblueprints.core.script - -import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException -import java.io.File -import java.io.InputStream -import java.io.Reader -import javax.script.ScriptEngineManager -import kotlin.script.experimental.api.ResultValue -import kotlin.script.experimental.api.ResultWithDiagnostics -import kotlin.script.experimental.api.resultOrNull -import kotlin.script.experimental.host.toScriptSource -import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate - - -open class BluePrintScriptService(classLoader: ClassLoader? = Thread.currentThread().contextClassLoader) { - - /** - * Get the Script Class instance - */ - inline fun scriptClassNewInstance(scriptFile: File, scriptClassName: String): T { - - val compilationConfiguration = createJvmCompilationConfigurationFromTemplate() - - val scriptEvaluator = BluePrintScriptEvaluator(scriptClassName) - - val evalResponse = BlueprintScriptingHost(scriptEvaluator).eval(scriptFile.toScriptSource(), compilationConfiguration, - null) - - when (evalResponse) { - is ResultWithDiagnostics.Success -> { - val returnValue = evalResponse.resultOrNull()?.returnValue as ResultValue.Value - return returnValue.value.castOrError() - } - is ResultWithDiagnostics.Failure -> { - throw BluePrintProcessorException(evalResponse.reports.joinToString("\n")) - } - else -> { - throw BluePrintProcessorException("Failed to process script ${scriptFile.absolutePath}") - } - } - - } - - val engine = ScriptEngineManager(classLoader).getEngineByExtension("kts") - - inline fun safeEval(evaluation: () -> R?) = try { - evaluation() - } catch (e: Exception) { - throw BluePrintProcessorException("Cannot load script", e) - } - - inline fun Any?.castOrError() = takeIf { it is T }?.let { it as T } - ?: throw IllegalArgumentException("Cannot cast $this to expected type ${T::class}") - - inline fun load(script: String): T = safeEval { engine.eval(script) }.castOrError() - - inline fun load(reader: Reader): T = safeEval { engine.eval(reader) }.castOrError() - - inline fun load(inputStream: InputStream): T = load(inputStream.reader()) - - inline fun loadAll(vararg inputStream: InputStream): List = inputStream.map(::load) -} diff --git a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BlueprintScriptingHost.kt b/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BlueprintScriptingHost.kt deleted file mode 100644 index bda20a44..00000000 --- a/components/core/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BlueprintScriptingHost.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * 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.onap.ccsdk.apps.controllerblueprints.core.script - -import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException -import org.slf4j.LoggerFactory -import kotlin.script.experimental.api.* -import kotlin.script.experimental.host.BasicScriptingHost -import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration -import kotlin.script.experimental.jvmhost.JvmScriptCompiler - -val defaultBlueprintScriptCompiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration) - -open class BlueprintScriptingHost(evaluator: ScriptEvaluator -) : BasicScriptingHost(defaultBlueprintScriptCompiler, evaluator) { - - override fun eval( - script: SourceCode, - scriptCompilationConfiguration: ScriptCompilationConfiguration, - configuration: ScriptEvaluationConfiguration? - ): ResultWithDiagnostics = - - runInCoroutineContext { - - compiler(script, scriptCompilationConfiguration) - .onSuccess { - evaluator(it, configuration) - } - } -} - - -open class BluePrintScriptEvaluator(private val scriptClassName: String) : ScriptEvaluator { - - val log = LoggerFactory.getLogger(BluePrintScriptEvaluator::class.java)!! - - override suspend operator fun invoke( - compiledScript: CompiledScript<*>, - scriptEvaluationConfiguration: ScriptEvaluationConfiguration? - ): ResultWithDiagnostics = - try { - val res = compiledScript.getClass(scriptEvaluationConfiguration) - when (res) { - is ResultWithDiagnostics.Failure -> res - is ResultWithDiagnostics.Success -> { - val scriptClass = res.value - val args = ArrayList() - scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.providedProperties)?.forEach { - args.add(it.value) - } - scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.implicitReceivers)?.let { - args.addAll(it) - } - scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.constructorArgs)?.let { - args.addAll(it) - } - - val completeScriptClass = "Script\$$scriptClassName" - log.info("Searching for class type($completeScriptClass)") - /** - * Search for Class Name - */ - val instanceClass = scriptClass.java.classes - .single { it.name == completeScriptClass } - //.single { it.name == "Script\$SampleBlueprintsFunctionNode" } - - - val instance = instanceClass.newInstance() - ?: throw BluePrintProcessorException("failed to create instance from the script") - - ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Value(completeScriptClass, - instance, instance.javaClass.typeName), - scriptEvaluationConfiguration)) - } - } - } catch (e: Throwable) { - ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script")) - } -} \ No newline at end of file diff --git a/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptServiceTest.kt b/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptServiceTest.kt deleted file mode 100644 index 5c5ad3ba..00000000 --- a/components/core/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/core/script/BluePrintScriptServiceTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * - * 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.onap.ccsdk.apps.controllerblueprints.core.script - -import org.junit.Ignore -import org.junit.Test -import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BlueprintFunctionNode -import java.io.File -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class BluePrintScriptServiceTest { - - @Test - fun `invoke script`() { - val scriptContent = "11 + 11" - val value = BluePrintScriptService() - .load(scriptContent) - assertEquals(22, value, "failed to execute command") - } - - @Test - @Ignore - fun `invoke script component node`() { - - //println(classpathFromClasspathProperty()?.joinToString("\n")) - - val scriptFile = File("src/test/resources/scripts/SampleBlueprintFunctionNode.kts") - - val functionNode = BluePrintScriptService() - .scriptClassNewInstance>(scriptFile, - "SampleBlueprintFunctionNode") - assertNotNull(functionNode, "failed to get instance from script") - } -} \ No newline at end of file diff --git a/components/parent/pom.xml b/components/parent/pom.xml index b53f9f11..6d5c2c14 100644 --- a/components/parent/pom.xml +++ b/components/parent/pom.xml @@ -29,11 +29,11 @@ Components Parent pom - 2.1.1.RELEASE - 5.1.3.RELEASE - 1.3.11 - 1.3.11 - 1.1.0 + 2.1.2.RELEASE + 5.1.4.RELEASE + 1.3.20 + 1.3.20 + 1.1.1 1.18.0 3.6.1 1.0.0 @@ -307,22 +307,6 @@ com.fasterxml.jackson.module jackson-module-kotlin - - org.jetbrains.kotlin - kotlin-compiler-embeddable - - - org.jetbrains.kotlin - kotlin-scripting-jvm-host - - - - - org.jetbrains.kotlin - kotlin-compiler - - - io.grpc diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml index be187726..472b466b 100755 --- a/ms/blueprintsprocessor/parent/pom.xml +++ b/ms/blueprintsprocessor/parent/pom.xml @@ -31,11 +31,11 @@ Blueprints Processor Parent Blueprints Processor Parent - 2.1.1.RELEASE - 5.1.3.RELEASE - 1.3.11 - 1.3.11 - 1.1.0 + 2.1.2.RELEASE + 5.1.4.RELEASE + 1.3.20 + 1.3.20 + 1.1.1 1.18.0 3.6.1 1.0.0 @@ -130,16 +130,23 @@ kotlin-stdlib-common ${kotlin.version} + + org.jetbrains.kotlin kotlin-scripting-jvm-host ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-compile + + org.jetbrains.kotlin kotlin-compiler-embeddable ${kotlin.version} - runtime org.jetbrains.kotlin diff --git a/ms/controllerblueprints/application/src/main/resources/application.properties b/ms/controllerblueprints/application/src/main/resources/application.properties index b6d509ce..ec61be48 100755 --- a/ms/controllerblueprints/application/src/main/resources/application.properties +++ b/ms/controllerblueprints/application/src/main/resources/application.properties @@ -41,7 +41,7 @@ spring.jpa.properties.hibernate.use_sql_comments=true spring.jpa.properties.hibernate.format_sql=true # spring.datasource.url, spring.datasource.username,spring.datasource.password may be overridden by ENV variables -spring.datasource.url=jdbc:mysql://db:3306/sdnctl +spring.datasource.url=jdbc:mysql://localhost:3306/sdnctl spring.datasource.username=sdnctl spring.datasource.password=sdnctl spring.datasource.driver-class-name=org.mariadb.jdbc.Driver diff --git a/ms/controllerblueprints/modules/blueprint-scripts/pom.xml b/ms/controllerblueprints/modules/blueprint-scripts/pom.xml new file mode 100644 index 00000000..46c88b4c --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/pom.xml @@ -0,0 +1,59 @@ + + + + + + modules + org.onap.ccsdk.apps.controllerblueprints + 0.4.1-SNAPSHOT + + 4.0.0 + blueprint-scripts + Controller Blueprints Scripts + + + + org.onap.ccsdk.apps.controllerblueprints + resource-dict + + + org.jetbrains.kotlin + kotlin-compiler-embeddable + + + org.jetbrains.kotlin + kotlin-scripting-jvm-host + + + org.jetbrains.kotlin + kotlin-compiler + + + + + org.jetbrains.kotlin + kotlin-script-util + + + org.jetbrains.kotlin + kotlin-script-runtime + + + + \ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompiledScript.kt b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompiledScript.kt new file mode 100644 index 00000000..8ac915bd --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompiledScript.kt @@ -0,0 +1,56 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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.onap.ccsdk.apps.controllerblueprints.scripts + +import java.io.File +import java.io.Serializable +import java.net.URL +import java.net.URLClassLoader +import kotlin.reflect.KClass +import kotlin.script.experimental.api.* + +open class BluePrintCompiledScript( + private val scriptCompilationConfiguration: ScriptCompilationConfiguration, + private val compiledJar: File) : + CompiledScript, Serializable { + + lateinit var scriptClassFQName: String + + override val compilationConfiguration: ScriptCompilationConfiguration + get() = scriptCompilationConfiguration + + override suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration?): ResultWithDiagnostics> = try { + + val baseClassLoader = Thread.currentThread().contextClassLoader + + val urls = arrayListOf() + urls.add(compiledJar.toURI().toURL()) + val classLoaderWithDependencies = URLClassLoader(urls.toTypedArray(), baseClassLoader) + + val clazz = classLoaderWithDependencies.loadClass(scriptClassFQName).kotlin + clazz.asSuccess() + } catch (e: Throwable) { + ResultWithDiagnostics.Failure( + ScriptDiagnostic( + "Unable to instantiate class $scriptClassFQName", + exception = e + ) + ) + } + +} + diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompilerProxy.kt b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompilerProxy.kt new file mode 100644 index 00000000..7e9e8688 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintCompilerProxy.kt @@ -0,0 +1,150 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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.onap.ccsdk.apps.controllerblueprints.scripts + +import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots +import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback +import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +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.JvmClasspathRoot +import org.jetbrains.kotlin.config.* +import org.slf4j.LoggerFactory +import java.io.File +import kotlin.script.experimental.api.* +import kotlin.script.experimental.host.ScriptingHostConfiguration +import kotlin.script.experimental.jvm.util.classpathFromClasspathProperty +import kotlin.script.experimental.jvmhost.KJvmCompilerProxy + +open class BluePrintsCompilerProxy(private val hostConfiguration: ScriptingHostConfiguration) : KJvmCompilerProxy { + + private val log = LoggerFactory.getLogger(BluePrintsCompilerProxy::class.java)!! + + override fun compile(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration) + : ResultWithDiagnostics> { + + val messageCollector = ScriptDiagnosticsMessageCollector() + + fun failure(vararg diagnostics: ScriptDiagnostic): ResultWithDiagnostics.Failure = + ResultWithDiagnostics.Failure(*messageCollector.diagnostics.toTypedArray(), *diagnostics) + + // Compile the Code + try { + + log.trace("Scripting Host Configuration : $hostConfiguration") + + setIdeaIoUseFallback() + + val blueprintSourceCode = script as BluePrintSourceCode + + val compiledJarFile = blueprintSourceCode.targetJarFile + + if (!compiledJarFile.exists() || blueprintSourceCode.regenerate) { + + var environment: KotlinCoreEnvironment? = null + + val rootDisposable = Disposer.newDisposable() + + val compilerConfiguration = CompilerConfiguration().apply { + + put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) + put(CommonConfigurationKeys.MODULE_NAME, blueprintSourceCode.moduleName) + put(JVMConfigurationKeys.OUTPUT_JAR, compiledJarFile) + put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, false) + + // Load Current Class loader to Compilation Class loader + val currentClassLoader = classpathFromClasspathProperty() + currentClassLoader?.forEach { + add(CLIConfigurationKeys.CONTENT_ROOTS, JvmClasspathRoot(it)) + } + + // Add all Kotlin Sources + addKotlinSourceRoots(blueprintSourceCode.blueprintKotlinSources) + + languageVersionSettings = LanguageVersionSettingsImpl( + LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, mapOf(AnalysisFlags.skipMetadataVersionCheck to true) + ) + } + + //log.info("Executing with compiler configuration : $compilerConfiguration") + + environment = KotlinCoreEnvironment.createForProduction(rootDisposable, compilerConfiguration, + EnvironmentConfigFiles.JVM_CONFIG_FILES) + + // Compile Kotlin Sources + val compiled = KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment) + + log.info("Generated jar(${compiledJarFile.absolutePath}) status : $compiled}") + + val analyzerWithCompilerReport = AnalyzerWithCompilerReport(messageCollector, + environment.configuration.languageVersionSettings) + + if (analyzerWithCompilerReport.hasErrors()) { + return failure() + } + } + + val res = BluePrintCompiledScript(scriptCompilationConfiguration, compiledJarFile) + + return ResultWithDiagnostics.Success(res, messageCollector.diagnostics) + + } catch (ex: Throwable) { + return failure(ex.asDiagnostics()) + } + } +} + +class ScriptDiagnosticsMessageCollector : MessageCollector { + + private val _diagnostics = arrayListOf() + + val diagnostics: List get() = _diagnostics + + override fun clear() { + _diagnostics.clear() + } + + override fun hasErrors(): Boolean = + _diagnostics.any { it.severity == ScriptDiagnostic.Severity.ERROR } + + + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { + val mappedSeverity = when (severity) { + CompilerMessageSeverity.EXCEPTION, + CompilerMessageSeverity.ERROR -> ScriptDiagnostic.Severity.ERROR + CompilerMessageSeverity.STRONG_WARNING, + CompilerMessageSeverity.WARNING -> ScriptDiagnostic.Severity.WARNING + CompilerMessageSeverity.INFO -> ScriptDiagnostic.Severity.INFO + CompilerMessageSeverity.LOGGING -> ScriptDiagnostic.Severity.DEBUG + else -> null + } + if (mappedSeverity != null) { + val mappedLocation = location?.let { + if (it.line < 0 && it.column < 0) null // special location created by CompilerMessageLocation.create + else SourceCode.Location(SourceCode.Position(it.line, it.column)) + } + _diagnostics.add(ScriptDiagnostic(message, mappedSeverity, location?.path, mappedLocation)) + } + } +} + diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintScriptConfiguration.kt b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintScriptConfiguration.kt new file mode 100644 index 00000000..3b3a5907 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BluePrintScriptConfiguration.kt @@ -0,0 +1,61 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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.onap.ccsdk.apps.controllerblueprints.scripts + +import java.io.File +import kotlin.script.experimental.annotations.KotlinScript +import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.SourceCode +import kotlin.script.experimental.api.defaultImports +import kotlin.script.experimental.jvm.jvm +import kotlin.script.experimental.jvm.util.classpathFromClassloader + +@KotlinScript( + fileExtension = "cba.kts", + compilationConfiguration = BluePrintScripCompilationConfiguration::class, + displayName = "Controller Blueprint Archive Kotlin Scripts" +) +abstract class BluePrintKotlinScript + +object BluePrintScripCompilationConfiguration : ScriptCompilationConfiguration( + { + defaultImports( + "org.onap.ccsdk.apps.controllerblueprints.core.*", + "org.onap.ccsdk.apps.controllerblueprints.core.data.*", + "org.onap.ccsdk.apps.controllerblueprints.core.interfaces.*", + "org.onap.ccsdk.apps.controllerblueprints.core.services.*", + "org.onap.ccsdk.apps.controllerblueprints.core.utils.*") + jvm { + classpathFromClassloader(BluePrintScripCompilationConfiguration::class.java.classLoader) + } + } +) + +open class BluePrintSourceCode : SourceCode { + lateinit var blueprintKotlinSources: MutableList + lateinit var moduleName: String + lateinit var targetJarFile: File + var regenerate: Boolean = false + + override val text: String + get() = "" + + override val locationId: String? = null + + override val name: String? + get() = moduleName +} diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHost.kt b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHost.kt new file mode 100644 index 00000000..59ce4abb --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHost.kt @@ -0,0 +1,92 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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.onap.ccsdk.apps.controllerblueprints.scripts + +import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintProcessorException +import org.slf4j.LoggerFactory +import java.util.* +import kotlin.script.experimental.api.* +import kotlin.script.experimental.host.BasicScriptingHost +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import kotlin.script.experimental.jvmhost.JvmScriptCompiler +import kotlin.script.experimental.jvmhost.impl.withDefaults + +val blueprintScriptCompiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration, + BluePrintsCompilerProxy(defaultJvmScriptingHostConfiguration.withDefaults())) + +open class BlueprintScriptingHost(evaluator: ScriptEvaluator) : BasicScriptingHost(blueprintScriptCompiler, evaluator) { + + override fun eval( + script: SourceCode, + scriptCompilationConfiguration: ScriptCompilationConfiguration, + configuration: ScriptEvaluationConfiguration? + ): ResultWithDiagnostics = + + runInCoroutineContext { + + compiler(script, scriptCompilationConfiguration) + .onSuccess { + evaluator(it, configuration) + } + } +} + + +open class BluePrintScriptEvaluator(private val scriptClassName: String) : ScriptEvaluator { + + private val log = LoggerFactory.getLogger(BluePrintScriptEvaluator::class.java)!! + + override suspend operator fun invoke( + compiledScript: CompiledScript<*>, + scriptEvaluationConfiguration: ScriptEvaluationConfiguration? + ): ResultWithDiagnostics = + try { + log.info("Getting class name($scriptClassName) of type() from the compiled sources ") + val bluePrintCompiledScript = compiledScript as BluePrintCompiledScript + bluePrintCompiledScript.scriptClassFQName = scriptClassName + + val res = compiledScript.getClass(scriptEvaluationConfiguration) + when (res) { + is ResultWithDiagnostics.Failure -> res + is ResultWithDiagnostics.Success -> { + + val scriptClass = res.value + val args = ArrayList() + scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.providedProperties)?.forEach { + args.add(it.value) + } + scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.implicitReceivers)?.let { + args.addAll(it) + } + scriptEvaluationConfiguration?.get(ScriptEvaluationConfiguration.constructorArgs)?.let { + args.addAll(it) + } + + val instance = scriptClass.java.newInstance() as? T + ?: throw BluePrintProcessorException("failed to create instance from the script") + + log.info("Created script instance successfully....") + + ResultWithDiagnostics.Success(EvaluationResult(ResultValue.Value(scriptClass.qualifiedName!!, + instance, "", instance), + scriptEvaluationConfiguration)) + } + } + } catch (e: Throwable) { + ResultWithDiagnostics.Failure(e.asDiagnostics("Error evaluating script")) + } +} \ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHostTest.kt b/ms/controllerblueprints/modules/blueprint-scripts/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHostTest.kt new file mode 100644 index 00000000..4b6f2a47 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/test/kotlin/org/onap/ccsdk/apps/controllerblueprints/scripts/BlueprintScriptingHostTest.kt @@ -0,0 +1,88 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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.onap.ccsdk.apps.controllerblueprints.scripts + + +import org.apache.commons.io.FileUtils +import org.junit.Ignore +import org.junit.Test +import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BlueprintFunctionNode +import java.io.File +import kotlin.script.experimental.jvm.util.classpathFromClass +import kotlin.script.experimental.jvm.util.classpathFromClassloader +import kotlin.script.experimental.jvm.util.classpathFromClasspathProperty +import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate + +class BlueprintScriptingHostTest { + + @Test + @Ignore + fun `test classpaths`() { + + println(" *********** classpathFromClass *********** ") + classpathFromClass(BlueprintScriptingHostTest::class.java.classLoader, + BlueprintScriptingHostTest::class)!! + .forEach(::println) + + println(" *********** classpathFromClassloader *********** ") + classpathFromClassloader(BlueprintScriptingHostTest::class.java.classLoader)!! + .forEach(::println) + + println(" *********** classpathFromClasspathProperty *********** ") + classpathFromClasspathProperty()!! + .forEach(::println) + } + + @Test + fun `test same script two folders`() { + + FileUtils.forceMkdir(File("target/scripts1/")) + FileUtils.forceMkdir(File("target/scripts2/")) + + val scriptSource1 = BluePrintSourceCode() + scriptSource1.moduleName = "blueprint-test-script" + + scriptSource1.targetJarFile = File("target/scripts1/blueprint-script-generated.jar") + val sources1: MutableList = arrayListOf() + sources1.add("src/test/resources/scripts1") + scriptSource1.blueprintKotlinSources = sources1 + + val scriptClassName = "Simple_cba\$SampleComponentFunction" + + val compilationConfiguration = createJvmCompilationConfigurationFromTemplate() + + val scriptEvaluator = BluePrintScriptEvaluator>(scriptClassName) + + val scriptSource2 = BluePrintSourceCode() + scriptSource2.moduleName = "blueprint-test-script" + + scriptSource2.targetJarFile = File("target/scripts2/blueprint-script-generated.jar") + val sources2: MutableList = arrayListOf() + sources2.add("src/test/resources/scripts2") + scriptSource2.blueprintKotlinSources = sources2 + + for (i in 1..2) { + val evalResponse = BlueprintScriptingHost(scriptEvaluator).eval(scriptSource1, compilationConfiguration, + null) + } + + for (i in 1..2) { + val evalResponse = BlueprintScriptingHost(scriptEvaluator).eval(scriptSource2, compilationConfiguration, + null) + } + } +} \ No newline at end of file diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts1/simple.cba.kts b/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts1/simple.cba.kts new file mode 100644 index 00000000..9f61c649 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts1/simple.cba.kts @@ -0,0 +1,55 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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. + */ + +import org.onap.ccsdk.apps.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.apps.controllerblueprints.core.data.ServiceTemplate +import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BlueprintFunctionNode +import org.springframework.stereotype.Service + +@Service +open class SampleComponentFunction : BlueprintFunctionNode { + + override fun getName(): String { + println("Printing Name....." + "sample".asJsonPrimitive()) + return "my Name" + } + + override fun prepareRequest(executionRequest: String): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun process(executionRequest: String) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun recover(runtimeException: RuntimeException, executionRequest: String) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun prepareResponse(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun apply(t: String): String { + return "Script 1 response - $t" + } +} + +val blueprintFunction = SampleComponentFunction() + +val serviceTemplate = ServiceTemplate() + +println("Simple script printing....") diff --git a/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts2/simple.cba.kts b/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts2/simple.cba.kts new file mode 100644 index 00000000..84517254 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-scripts/src/test/resources/scripts2/simple.cba.kts @@ -0,0 +1,55 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * 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. + */ + +import org.onap.ccsdk.apps.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.apps.controllerblueprints.core.data.ServiceTemplate +import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BlueprintFunctionNode +import org.springframework.stereotype.Service + +@Service +open class SampleComponentFunction : BlueprintFunctionNode { + + override fun getName(): String { + println("Printing Name....." + "sample".asJsonPrimitive()) + return "my Name" + } + + override fun prepareRequest(executionRequest: String): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun process(executionRequest: String) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun recover(runtimeException: RuntimeException, executionRequest: String) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun prepareResponse(): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun apply(t: String): String { + return "Script 2 response - $t" + } +} + +val blueprintFunction = SampleComponentFunction() + +val serviceTemplate = ServiceTemplate() + +println("Simple script printing....") diff --git a/ms/controllerblueprints/modules/pom.xml b/ms/controllerblueprints/modules/pom.xml index 3857ef5d..834db24e 100644 --- a/ms/controllerblueprints/modules/pom.xml +++ b/ms/controllerblueprints/modules/pom.xml @@ -30,6 +30,7 @@ service blueprint-validation db-resources + blueprint-scripts diff --git a/ms/controllerblueprints/modules/service/pom.xml b/ms/controllerblueprints/modules/service/pom.xml index 9868b17b..73fe0739 100644 --- a/ms/controllerblueprints/modules/service/pom.xml +++ b/ms/controllerblueprints/modules/service/pom.xml @@ -30,10 +30,6 @@ - - org.onap.ccsdk.apps.controllerblueprints - core - org.onap.ccsdk.apps.controllerblueprints db-resources @@ -44,7 +40,7 @@ org.onap.ccsdk.apps.controllerblueprints - resource-dict + blueprint-scripts org.apache.velocity diff --git a/ms/controllerblueprints/parent/pom.xml b/ms/controllerblueprints/parent/pom.xml index 578a0c7e..8cbc98e0 100644 --- a/ms/controllerblueprints/parent/pom.xml +++ b/ms/controllerblueprints/parent/pom.xml @@ -28,11 +28,11 @@ Controller Blueprints Parent pom - 2.1.1.RELEASE - 5.1.3.RELEASE - 1.3.11 - 1.3.11 - 1.1.0 + 2.1.2.RELEASE + 5.1.4.RELEASE + 1.3.20 + 1.3.20 + 1.1.1 1.18.0 3.6.1 1.0.0 @@ -113,16 +113,23 @@ kotlin-stdlib-common ${kotlin.version} + + org.jetbrains.kotlin kotlin-scripting-jvm-host ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-compile + + org.jetbrains.kotlin kotlin-compiler-embeddable ${kotlin.version} - runtime org.jetbrains.kotlin @@ -203,27 +210,32 @@ org.onap.ccsdk.apps.controllerblueprints - service + resource-dict ${project.version} org.onap.ccsdk.apps.controllerblueprints - application + db-resources ${project.version} org.onap.ccsdk.apps.controllerblueprints - resource-dict + blueprint-validation ${project.version} org.onap.ccsdk.apps.controllerblueprints - db-resources + blueprint-scripts ${project.version} org.onap.ccsdk.apps.controllerblueprints - blueprint-validation + service + ${project.version} + + + org.onap.ccsdk.apps.controllerblueprints + application ${project.version} @@ -274,6 +286,10 @@ com.jayway.jsonpath json-path + + com.google.guava + guava + io.springfox springfox-swagger2 -- cgit 1.2.3-korg