mirror of https://github.com/apache/nifi.git
NIFI-8730: Invalidate (don't evaluate) empty script in scripting components
Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #5184.
This commit is contained in:
parent
b27c2b500e
commit
632fbcca7d
|
@ -241,11 +241,10 @@ public class BaseScriptedLookupService extends AbstractScriptedControllerService
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (scriptNeedsReload.get() || lookupService.get() == null) {
|
if (scriptNeedsReload.get() || lookupService.get() == null) {
|
||||||
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
scriptNeedsReload.set(reloadScriptFile(scriptingComponentHelper.getScriptPath()));
|
||||||
} else {
|
} else {
|
||||||
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
scriptNeedsReload.set(reloadScriptBody(scriptingComponentHelper.getScriptBody()));
|
||||||
}
|
}
|
||||||
scriptNeedsReload.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -215,11 +215,10 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (scriptNeedsReload.get() || processor.get() == null) {
|
if (scriptNeedsReload.get() || processor.get() == null) {
|
||||||
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
scriptNeedsReload.set(reloadScriptFile(scriptingComponentHelper.getScriptPath()));
|
||||||
} else {
|
} else {
|
||||||
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
scriptNeedsReload.set(reloadScriptBody(scriptingComponentHelper.getScriptBody()));
|
||||||
}
|
}
|
||||||
scriptNeedsReload.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +325,10 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
* @return Whether the script was successfully reloaded
|
* @return Whether the script was successfully reloaded
|
||||||
*/
|
*/
|
||||||
private boolean reloadScript(final String scriptBody) {
|
private boolean reloadScript(final String scriptBody) {
|
||||||
|
if (StringUtils.isEmpty(scriptBody)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// note we are starting here with a fresh listing of validation
|
// note we are starting here with a fresh listing of validation
|
||||||
// results since we are (re)loading a new/updated script. any
|
// results since we are (re)loading a new/updated script. any
|
||||||
// existing validation results are not relevant
|
// existing validation results are not relevant
|
||||||
|
@ -431,15 +434,14 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
// store the updated validation results
|
// store the updated validation results
|
||||||
validationResults.set(results);
|
validationResults.set(results);
|
||||||
|
|
||||||
// return whether there was any issues loading the configured script
|
// return whether there were any issues loading the configured script
|
||||||
return results.isEmpty();
|
return !results.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the validate() routine provided by the script, allowing for
|
* Invokes the validate() routine provided by the script, allowing for
|
||||||
* custom validation code. This method assumes there is a valid Processor
|
* custom validation code, if there is a valid Processor
|
||||||
* defined in the script and it has been loaded by the
|
* defined in the script and it has been loaded by the processor
|
||||||
* InvokeScriptedProcessor processor
|
|
||||||
*
|
*
|
||||||
* @param context The validation context to be passed into the custom
|
* @param context The validation context to be passed into the custom
|
||||||
* validate method
|
* validate method
|
||||||
|
@ -460,6 +462,12 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
return validationResults.get();
|
return validationResults.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection<ValidationResult> scriptingComponentHelperResults = scriptingComponentHelper.customValidate(context);
|
||||||
|
if (scriptingComponentHelperResults != null && !scriptingComponentHelperResults.isEmpty()) {
|
||||||
|
validationResults.set(scriptingComponentHelperResults);
|
||||||
|
return scriptingComponentHelperResults;
|
||||||
|
}
|
||||||
|
|
||||||
scriptingComponentHelper.setScriptEngineName(context.getProperty(scriptingComponentHelper.SCRIPT_ENGINE).getValue());
|
scriptingComponentHelper.setScriptEngineName(context.getProperty(scriptingComponentHelper.SCRIPT_ENGINE).getValue());
|
||||||
scriptingComponentHelper.setScriptPath(context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue());
|
scriptingComponentHelper.setScriptPath(context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue());
|
||||||
scriptingComponentHelper.setScriptBody(context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue());
|
scriptingComponentHelper.setScriptBody(context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue());
|
||||||
|
@ -476,7 +484,7 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
try {
|
try {
|
||||||
// defer to the underlying processor for validation, without the
|
// defer to the underlying processor for validation, without the
|
||||||
// invokescriptedprocessor properties
|
// invokescriptedprocessor properties
|
||||||
final Set<PropertyDescriptor> innerPropertyDescriptor = new HashSet<PropertyDescriptor>(scriptingComponentHelper.getDescriptors());
|
final Set<PropertyDescriptor> innerPropertyDescriptor = new HashSet<>(scriptingComponentHelper.getDescriptors());
|
||||||
|
|
||||||
ValidationContext innerValidationContext = new FilteredPropertiesValidationContextAdapter(context, innerPropertyDescriptor);
|
ValidationContext innerValidationContext = new FilteredPropertiesValidationContextAdapter(context, innerPropertyDescriptor);
|
||||||
final Collection<ValidationResult> instanceResults = instance.validate(innerValidationContext);
|
final Collection<ValidationResult> instanceResults = instance.validate(innerValidationContext);
|
||||||
|
@ -568,7 +576,10 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
|
||||||
|
|
||||||
@OnStopped
|
@OnStopped
|
||||||
public void stop(ProcessContext context) {
|
public void stop(ProcessContext context) {
|
||||||
invokeScriptedProcessorMethod("onStopped", context);
|
// If the script needs to be reloaded at this point, it is because it was empty
|
||||||
|
if (!scriptNeedsReload.get()) {
|
||||||
|
invokeScriptedProcessorMethod("onStopped", context);
|
||||||
|
}
|
||||||
scriptingComponentHelper.stop();
|
scriptingComponentHelper.stop();
|
||||||
processor.set(null);
|
processor.set(null);
|
||||||
scriptRunner = null;
|
scriptRunner = null;
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class ScriptedTransformRecord extends AbstractProcessor implements Search
|
||||||
@OnScheduled
|
@OnScheduled
|
||||||
public void setup(final ProcessContext context) throws IOException {
|
public void setup(final ProcessContext context) throws IOException {
|
||||||
if (!scriptingComponentHelper.isInitialized.get()) {
|
if (!scriptingComponentHelper.isInitialized.get()) {
|
||||||
scriptingComponentHelper.createResources();
|
scriptingComponentHelper.createResources(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptingComponentHelper.setupVariables(context);
|
scriptingComponentHelper.setupVariables(context);
|
||||||
|
|
|
@ -107,11 +107,10 @@ public class ScriptedRecordSink extends AbstractScriptedControllerService implem
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (scriptNeedsReload.get() || recordSink.get() == null) {
|
if (scriptNeedsReload.get() || recordSink.get() == null) {
|
||||||
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
scriptNeedsReload.set(reloadScriptFile(scriptingComponentHelper.getScriptPath()));
|
||||||
} else {
|
} else {
|
||||||
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
scriptNeedsReload.set(reloadScriptBody(scriptingComponentHelper.getScriptBody()));
|
||||||
}
|
}
|
||||||
scriptNeedsReload.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,11 +78,10 @@ public class ScriptedRulesEngine extends AbstractScriptedControllerService imple
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (scriptNeedsReload.get() || rulesEngine.get() == null) {
|
if (scriptNeedsReload.get() || rulesEngine.get() == null) {
|
||||||
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
scriptNeedsReload.set(reloadScriptFile(scriptingComponentHelper.getScriptPath()));
|
||||||
} else {
|
} else {
|
||||||
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
scriptNeedsReload.set(reloadScriptBody(scriptingComponentHelper.getScriptBody()));
|
||||||
}
|
}
|
||||||
scriptNeedsReload.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,11 +80,10 @@ public class ScriptedActionHandler extends AbstractScriptedControllerService imp
|
||||||
public void setup() {
|
public void setup() {
|
||||||
if (scriptNeedsReload.get() || actionHandler.get() == null) {
|
if (scriptNeedsReload.get() || actionHandler.get() == null) {
|
||||||
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
scriptNeedsReload.set(reloadScriptFile(scriptingComponentHelper.getScriptPath()));
|
||||||
} else {
|
} else {
|
||||||
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
scriptNeedsReload.set(reloadScriptBody(scriptingComponentHelper.getScriptBody()));
|
||||||
}
|
}
|
||||||
scriptNeedsReload.set(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ public abstract class AbstractScriptedControllerService extends AbstractControll
|
||||||
@Override
|
@Override
|
||||||
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
|
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
|
||||||
|
|
||||||
Collection<ValidationResult> commonValidationResults = super.customValidate(validationContext);
|
Collection<ValidationResult> commonValidationResults = new ArrayList<>(super.customValidate(validationContext));
|
||||||
commonValidationResults.addAll(scriptingComponentHelper.customValidate(validationContext));
|
commonValidationResults.addAll(scriptingComponentHelper.customValidate(validationContext));
|
||||||
|
|
||||||
if (!commonValidationResults.isEmpty()) {
|
if (!commonValidationResults.isEmpty()) {
|
||||||
|
@ -173,7 +173,7 @@ public abstract class AbstractScriptedControllerService extends AbstractControll
|
||||||
validationResults.set(results);
|
validationResults.set(results);
|
||||||
|
|
||||||
// return whether there was any issues loading the configured script
|
// return whether there was any issues loading the configured script
|
||||||
return results.isEmpty();
|
return !results.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,7 +52,6 @@ public class TestInvokeJavascript extends BaseScriptTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
|
public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
|
||||||
runner.setValidateExpressionUsage(false);
|
|
||||||
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
||||||
runner.setProperty(ScriptingComponentUtils.SCRIPT_FILE, "target/test/resources/javascript/test_reader.js");
|
runner.setProperty(ScriptingComponentUtils.SCRIPT_FILE, "target/test/resources/javascript/test_reader.js");
|
||||||
runner.setProperty(ScriptingComponentUtils.MODULES, "target/test/resources/javascript");
|
runner.setProperty(ScriptingComponentUtils.MODULES, "target/test/resources/javascript");
|
||||||
|
@ -146,7 +145,6 @@ public class TestInvokeJavascript extends BaseScriptTest {
|
||||||
@Test(expected = AssertionError.class)
|
@Test(expected = AssertionError.class)
|
||||||
public void testInvokeScriptCausesException() throws Exception {
|
public void testInvokeScriptCausesException() throws Exception {
|
||||||
final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
|
final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
|
||||||
runner.setValidateExpressionUsage(false);
|
|
||||||
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
||||||
runner.setProperty(ScriptingComponentUtils.SCRIPT_BODY, getFileContentsAsString(
|
runner.setProperty(ScriptingComponentUtils.SCRIPT_BODY, getFileContentsAsString(
|
||||||
TEST_RESOURCE_LOCATION + "javascript/testInvokeScriptCausesException.js")
|
TEST_RESOURCE_LOCATION + "javascript/testInvokeScriptCausesException.js")
|
||||||
|
@ -164,7 +162,6 @@ public class TestInvokeJavascript extends BaseScriptTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testScriptRoutesToFailure() throws Exception {
|
public void testScriptRoutesToFailure() throws Exception {
|
||||||
runner.setValidateExpressionUsage(false);
|
|
||||||
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
||||||
runner.setProperty(ScriptingComponentUtils.SCRIPT_BODY, getFileContentsAsString(
|
runner.setProperty(ScriptingComponentUtils.SCRIPT_BODY, getFileContentsAsString(
|
||||||
TEST_RESOURCE_LOCATION + "javascript/testScriptRoutesToFailure.js")
|
TEST_RESOURCE_LOCATION + "javascript/testScriptRoutesToFailure.js")
|
||||||
|
@ -177,4 +174,16 @@ public class TestInvokeJavascript extends BaseScriptTest {
|
||||||
final List<MockFlowFile> result = runner.getFlowFilesForRelationship("FAILURE");
|
final List<MockFlowFile> result = runner.getFlowFilesForRelationship("FAILURE");
|
||||||
assertFalse(result.isEmpty());
|
assertFalse(result.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests an empty script with Nashorn (which throws an NPE if it is loaded), this test verifies an empty script is not attempted to be loaded.
|
||||||
|
*
|
||||||
|
* @throws Exception Any error encountered while testing
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEmptyScript() throws Exception {
|
||||||
|
runner.setProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE, "ECMAScript");
|
||||||
|
runner.setProperty(ScriptingComponentUtils.SCRIPT_BODY, "");
|
||||||
|
runner.assertNotValid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class GroovyProcessor implements Processor {
|
||||||
@Override
|
@Override
|
||||||
void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
|
void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
|
||||||
def session = sessionFactory.createSession()
|
def session = sessionFactory.createSession()
|
||||||
def flowFile = session.get();
|
def flowFile = session.get()
|
||||||
if (flowFile == null) {
|
if (flowFile == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue