diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java index c67e8e8eb4..7d63724fc4 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java @@ -273,6 +273,7 @@ public class BaseScriptedLookupService extends AbstractScriptedControllerService // Find a custom configurator and invoke their eval() method ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase()); if (configurator != null) { + configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules()); configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules()); } else { // evaluate the script diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java index e05ec859af..82ec3ad634 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java @@ -232,6 +232,7 @@ public class ExecuteScript extends AbstractSessionFactoryProcessor implements Se // Evaluate the script with the configurator (if it exists) or the engine if (configurator != null) { + configurator.init(scriptEngine, scriptToRun, scriptingComponentHelper.getModules()); configurator.eval(scriptEngine, scriptToRun, scriptingComponentHelper.getModules()); } else { scriptEngine.eval(scriptToRun); diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java index 196e78cb7b..76005497a7 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java @@ -349,6 +349,7 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor { // Find a custom configurator and invoke their eval() method ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase()); if (configurator != null) { + configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules()); configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules()); } else { // evaluate the script diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java index f30c7da7bd..c734976e22 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java @@ -33,7 +33,7 @@ public interface ScriptEngineConfigurator { URL[] getModuleURLsForClasspath(String[] modulePaths, ComponentLog log); - Object init(ScriptEngine engine, String[] modulePaths) throws ScriptException; + Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException; Object eval(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException; diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java index ac9f2b7722..25d0563d65 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java @@ -91,6 +91,7 @@ public class ScriptedReader extends AbstractScriptedRecordFactory "sys.path.append(" + PyString.encode_UnicodeEscape(modulePath, true) + ")") + .collect(Collectors.joining("\n")); + final CompiledScript compiled = ((Compilable) engine).compile(prefix + scriptBody); + compiledScriptRef.set(compiled); + } + return compiledScriptRef.get(); } @Override @@ -60,13 +67,7 @@ public class JythonScriptEngineConfigurator implements ScriptEngineConfigurator if (engine != null) { final CompiledScript existing = compiledScriptRef.get(); if (existing == null) { - - // Add prefix for import sys and all jython modules - String prefix = "import sys\n" - + Arrays.stream(modulePaths).map((modulePath) -> "sys.path.append(" + PyString.encode_UnicodeEscape(modulePath, true) + ")") - .collect(Collectors.joining("\n")); - final CompiledScript compiled = ((Compilable) engine).compile(prefix + scriptBody); - compiledScriptRef.compareAndSet(null, compiled); + throw new ScriptException("Jython script has not been compiled, the processor must be restarted."); } returnValue = compiledScriptRef.get().eval(); } diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy similarity index 81% rename from nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy rename to nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy index f9c6876fbf..a77d4c754e 100644 --- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy @@ -58,8 +58,8 @@ import static org.mockito.Mockito.when * Unit tests for ScriptedReportingTask. */ @RunWith(JUnit4.class) -class ScriptedReportingTaskGroovyTest { - private static final Logger logger = LoggerFactory.getLogger(ScriptedReportingTaskGroovyTest) +class ScriptedReportingTaskTest { + private static final Logger logger = LoggerFactory.getLogger(ScriptedReportingTaskTest) def task def runner def scriptingComponent @@ -197,6 +197,50 @@ class ScriptedReportingTaskGroovyTest { } + @Test + void testVMEventsJythonScript() { + + def properties = [:] as Map + task.getSupportedPropertyDescriptors().each { PropertyDescriptor descriptor -> + properties.put(descriptor, descriptor.getDefaultValue()) + } + + // Mock the ConfigurationContext for setup(...) + def configurationContext = mock(ConfigurationContext) + when(configurationContext.getProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE)) + .thenReturn(new MockPropertyValue('python')) + when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_FILE)) + .thenReturn(new MockPropertyValue('target/test/resources/jython/test_log_vm_stats.py')) + when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_BODY)) + .thenReturn(new MockPropertyValue(null)) + when(configurationContext.getProperty(ScriptingComponentUtils.MODULES)) + .thenReturn(new MockPropertyValue(null)) + + // Set up ReportingContext + def context = mock(ReportingContext) + when(context.getStateManager()).thenReturn(new MockStateManager(task)) + doAnswer({ invocation -> + PropertyDescriptor descriptor = invocation.getArgumentAt(0, PropertyDescriptor) + return new MockPropertyValue(properties[descriptor]) + } as Answer + ).when(context).getProperty(any(PropertyDescriptor)) + + + def logger = mock(ComponentLog) + def initContext = mock(ReportingInitializationContext) + when(initContext.getIdentifier()).thenReturn(UUID.randomUUID().toString()) + when(initContext.getLogger()).thenReturn(logger) + + task.initialize initContext + task.setup configurationContext + task.onTrigger context + def se = task.scriptEngine + // This script should store a variable called x with a map of stats to values + assertTrue se.x?.uptime >= 0 + task.offerScriptEngine(se) + + } + class MockScriptedReportingTask extends ScriptedReportingTask implements AccessibleScriptingComponentHelper { def getScriptEngine() { return scriptingComponentHelper.engineQ.poll() diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py new file mode 100644 index 0000000000..219dc44d75 --- /dev/null +++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py @@ -0,0 +1,29 @@ +#! /usr/bin/python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +x = { + 'uptime': vmMetrics.uptime(), + 'heapUsed': vmMetrics.heapUsed(None), + 'heapUsage': vmMetrics.heapUsage(), + 'nonHeapUsage': vmMetrics.nonHeapUsage(), + 'threadCount': vmMetrics.threadCount(), + 'daemonThreadCount': vmMetrics.daemonThreadCount(), + 'fileDescriptorUsage': vmMetrics.fileDescriptorUsage() +}