mirror of https://github.com/apache/nifi.git
NIFI-3938: Added ScriptedLookupService, some refactor for reusable scripting classes
This closes #1828. Signed-off-by: Andy LoPresto <alopresto@apache.org>
This commit is contained in:
parent
d4f0c1d048
commit
9294a26139
|
@ -46,6 +46,10 @@
|
||||||
<groupId>org.apache.nifi</groupId>
|
<groupId>org.apache.nifi</groupId>
|
||||||
<artifactId>nifi-record</artifactId>
|
<artifactId>nifi-record</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.nifi</groupId>
|
||||||
|
<artifactId>nifi-lookup-service-api</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.groovy</groupId>
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
<artifactId>groovy-all</artifactId>
|
<artifactId>groovy-all</artifactId>
|
||||||
|
|
|
@ -0,0 +1,375 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.apache.nifi.lookup.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.annotation.behavior.Restricted;
|
||||||
|
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||||
|
import org.apache.nifi.annotation.documentation.Tags;
|
||||||
|
import org.apache.nifi.annotation.lifecycle.OnDisabled;
|
||||||
|
import org.apache.nifi.annotation.lifecycle.OnEnabled;
|
||||||
|
import org.apache.nifi.components.ConfigurableComponent;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.components.ValidationResult;
|
||||||
|
import org.apache.nifi.components.state.StateManager;
|
||||||
|
import org.apache.nifi.controller.ConfigurationContext;
|
||||||
|
import org.apache.nifi.controller.ControllerServiceInitializationContext;
|
||||||
|
import org.apache.nifi.controller.ControllerServiceLookup;
|
||||||
|
import org.apache.nifi.logging.ComponentLog;
|
||||||
|
import org.apache.nifi.lookup.LookupFailureException;
|
||||||
|
import org.apache.nifi.lookup.LookupService;
|
||||||
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
|
import org.apache.nifi.script.AbstractScriptedControllerService;
|
||||||
|
|
||||||
|
import javax.script.Invocable;
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Controller service that allows the user to script the lookup operation to be performed (by LookupRecord, e.g.)
|
||||||
|
*/
|
||||||
|
@Tags({"lookup", "record", "script", "invoke", "groovy", "python", "jython", "jruby", "ruby", "javascript", "js", "lua", "luaj", "restricted"})
|
||||||
|
@CapabilityDescription("Allows the user to provide a scripted LookupService instance in order to enrich records from an incoming flow file.")
|
||||||
|
@Restricted("Provides operator the ability to execute arbitrary code assuming all permissions that NiFi has.")
|
||||||
|
public class ScriptedLookupService extends AbstractScriptedControllerService implements LookupService<Object> {
|
||||||
|
|
||||||
|
protected final AtomicReference<LookupService<Object>> lookupService = new AtomicReference<>();
|
||||||
|
|
||||||
|
private volatile String kerberosServicePrincipal = null;
|
||||||
|
private volatile File kerberosConfigFile = null;
|
||||||
|
private volatile File kerberosServiceKeytab = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Object> lookup(String key) throws LookupFailureException {
|
||||||
|
// Delegate the lookup() call to the scripted LookupService
|
||||||
|
return lookupService.get().lookup(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getValueType() {
|
||||||
|
// Delegate the getValueType() call to the scripted LookupService
|
||||||
|
return lookupService.get().getValueType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init(final ControllerServiceInitializationContext context) {
|
||||||
|
kerberosServicePrincipal = context.getKerberosServicePrincipal();
|
||||||
|
kerberosConfigFile = context.getKerberosConfigurationFile();
|
||||||
|
kerberosServiceKeytab = context.getKerberosServiceKeytab();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of property descriptors supported by this processor. The
|
||||||
|
* list always includes properties such as script engine name, script file
|
||||||
|
* name, script body name, script arguments, and an external module path. If
|
||||||
|
* the scripted processor also defines supported properties, those are added
|
||||||
|
* to the list as well.
|
||||||
|
*
|
||||||
|
* @return a List of PropertyDescriptor objects supported by this processor
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
|
||||||
|
synchronized (scriptingComponentHelper.isInitialized) {
|
||||||
|
if (!scriptingComponentHelper.isInitialized.get()) {
|
||||||
|
scriptingComponentHelper.createResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<PropertyDescriptor> supportedPropertyDescriptors = new ArrayList<>();
|
||||||
|
supportedPropertyDescriptors.addAll(scriptingComponentHelper.getDescriptors());
|
||||||
|
|
||||||
|
final ConfigurableComponent instance = lookupService.get();
|
||||||
|
if (instance != null) {
|
||||||
|
try {
|
||||||
|
final List<PropertyDescriptor> instanceDescriptors = instance.getPropertyDescriptors();
|
||||||
|
if (instanceDescriptors != null) {
|
||||||
|
supportedPropertyDescriptors.addAll(instanceDescriptors);
|
||||||
|
}
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
final String message = "Unable to get property descriptors from Processor: " + t;
|
||||||
|
|
||||||
|
logger.error(message);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.error(message, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(supportedPropertyDescriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a PropertyDescriptor for the given name. This is for the user to
|
||||||
|
* be able to define their own properties which will be available as
|
||||||
|
* variables in the script
|
||||||
|
*
|
||||||
|
* @param propertyDescriptorName used to lookup if any property descriptors
|
||||||
|
* exist for that name
|
||||||
|
* @return a PropertyDescriptor object corresponding to the specified
|
||||||
|
* dynamic property name
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
||||||
|
return new PropertyDescriptor.Builder()
|
||||||
|
.name(propertyDescriptorName)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.dynamic(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles changes to this processor's properties. If changes are made to
|
||||||
|
* script- or engine-related properties, the script will be reloaded.
|
||||||
|
*
|
||||||
|
* @param descriptor of the modified property
|
||||||
|
* @param oldValue non-null property value (previous)
|
||||||
|
* @param newValue the new property value or if null indicates the property
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
final ConfigurableComponent instance = lookupService.get();
|
||||||
|
|
||||||
|
if (ScriptingComponentUtils.SCRIPT_FILE.equals(descriptor)
|
||||||
|
|| ScriptingComponentUtils.SCRIPT_BODY.equals(descriptor)
|
||||||
|
|| ScriptingComponentUtils.MODULES.equals(descriptor)
|
||||||
|
|| scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
||||||
|
scriptNeedsReload.set(true);
|
||||||
|
// Need to reset scriptEngine if the value has changed
|
||||||
|
if (scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
||||||
|
scriptEngine = null;
|
||||||
|
}
|
||||||
|
} else if (instance != null) {
|
||||||
|
// If the script provides a ConfigurableComponent, call its onPropertyModified() method
|
||||||
|
try {
|
||||||
|
instance.onPropertyModified(descriptor, oldValue, newValue);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
final String message = "Unable to invoke onPropertyModified from scripted LookupService: " + e;
|
||||||
|
logger.error(message, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnEnabled
|
||||||
|
public void onEnabled(final ConfigurationContext context) {
|
||||||
|
synchronized (scriptingComponentHelper.isInitialized) {
|
||||||
|
if (!scriptingComponentHelper.isInitialized.get()) {
|
||||||
|
scriptingComponentHelper.createResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onEnabled(context);
|
||||||
|
|
||||||
|
// Call an non-interface method onEnabled(context), to allow a scripted LookupService the chance to set up as necessary
|
||||||
|
final Invocable invocable = (Invocable) scriptEngine;
|
||||||
|
if (configurationContext != null) {
|
||||||
|
try {
|
||||||
|
// Get the actual object from the script engine, versus the proxy stored in lookupService. The object may have additional methods,
|
||||||
|
// where lookupService is a proxied interface
|
||||||
|
final Object obj = scriptEngine.get("lookupService");
|
||||||
|
if (obj != null) {
|
||||||
|
try {
|
||||||
|
invocable.invokeMethod(obj, "onEnabled", context);
|
||||||
|
} catch (final NoSuchMethodException nsme) {
|
||||||
|
if (getLogger().isDebugEnabled()) {
|
||||||
|
getLogger().debug("Configured script LookupService does not contain an onEnabled() method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ScriptException("No LookupService was defined by the script.");
|
||||||
|
}
|
||||||
|
} catch (ScriptException se) {
|
||||||
|
throw new ProcessException("Error executing onEnabled(context) method", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnDisabled
|
||||||
|
public void onDisabled(final ConfigurationContext context) {
|
||||||
|
// Call an non-interface method onDisabled(context), to allow a scripted LookupService the chance to shut down as necessary
|
||||||
|
final Invocable invocable = (Invocable) scriptEngine;
|
||||||
|
if (configurationContext != null) {
|
||||||
|
try {
|
||||||
|
// Get the actual object from the script engine, versus the proxy stored in lookupService. The object may have additional methods,
|
||||||
|
// where lookupService is a proxied interface
|
||||||
|
final Object obj = scriptEngine.get("lookupService");
|
||||||
|
if (obj != null) {
|
||||||
|
try {
|
||||||
|
invocable.invokeMethod(obj, "onDisabled", context);
|
||||||
|
} catch (final NoSuchMethodException nsme) {
|
||||||
|
if (getLogger().isDebugEnabled()) {
|
||||||
|
getLogger().debug("Configured script LookupService does not contain an onDisabled() method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ScriptException("No LookupService was defined by the script.");
|
||||||
|
}
|
||||||
|
} catch (ScriptException se) {
|
||||||
|
throw new ProcessException("Error executing onDisabled(context) method", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setup() {
|
||||||
|
// Create a single script engine, the Processor object is reused by each task
|
||||||
|
if (scriptEngine == null) {
|
||||||
|
scriptingComponentHelper.setup(1, getLogger());
|
||||||
|
scriptEngine = scriptingComponentHelper.engineQ.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scriptEngine == null) {
|
||||||
|
throw new ProcessException("No script engine available!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scriptNeedsReload.get() || lookupService.get() == null) {
|
||||||
|
if (ScriptingComponentHelper.isFile(scriptingComponentHelper.getScriptPath())) {
|
||||||
|
reloadScriptFile(scriptingComponentHelper.getScriptPath());
|
||||||
|
} else {
|
||||||
|
reloadScriptBody(scriptingComponentHelper.getScriptBody());
|
||||||
|
}
|
||||||
|
scriptNeedsReload.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the script RecordReaderFactory. This must be called within the lock.
|
||||||
|
*
|
||||||
|
* @param scriptBody An input stream associated with the script content
|
||||||
|
* @return Whether the script was successfully reloaded
|
||||||
|
*/
|
||||||
|
protected boolean reloadScript(final String scriptBody) {
|
||||||
|
// note we are starting here with a fresh listing of validation
|
||||||
|
// results since we are (re)loading a new/updated script. any
|
||||||
|
// existing validation results are not relevant
|
||||||
|
final Collection<ValidationResult> results = new HashSet<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// get the engine and ensure its invocable
|
||||||
|
if (scriptEngine instanceof Invocable) {
|
||||||
|
final Invocable invocable = (Invocable) scriptEngine;
|
||||||
|
|
||||||
|
// Find a custom configurator and invoke their eval() method
|
||||||
|
ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
|
||||||
|
if (configurator != null) {
|
||||||
|
configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
|
||||||
|
} else {
|
||||||
|
// evaluate the script
|
||||||
|
scriptEngine.eval(scriptBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get configured LookupService from the script (if it exists)
|
||||||
|
final Object obj = scriptEngine.get("lookupService");
|
||||||
|
if (obj != null) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// set the logger if the processor wants it
|
||||||
|
invocable.invokeMethod(obj, "setLogger", logger);
|
||||||
|
} catch (final NoSuchMethodException nsme) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Scripted LookupService does not contain a setLogger method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// record the processor for use later
|
||||||
|
final LookupService<Object> scriptedLookupService = invocable.getInterface(obj, LookupService.class);
|
||||||
|
lookupService.set(scriptedLookupService);
|
||||||
|
|
||||||
|
if (scriptedLookupService != null) {
|
||||||
|
try {
|
||||||
|
scriptedLookupService.initialize(new ControllerServiceInitializationContext() {
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return ScriptedLookupService.this.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentLog getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StateManager getStateManager() {
|
||||||
|
return ScriptedLookupService.this.getStateManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ControllerServiceLookup getControllerServiceLookup() {
|
||||||
|
return ScriptedLookupService.super.getControllerServiceLookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKerberosServicePrincipal() {
|
||||||
|
return ScriptedLookupService.this.kerberosServicePrincipal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getKerberosServiceKeytab() {
|
||||||
|
return ScriptedLookupService.this.kerberosServiceKeytab;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getKerberosConfigurationFile() {
|
||||||
|
return ScriptedLookupService.this.kerberosConfigFile;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (final Exception e) {
|
||||||
|
logger.error("Unable to initialize scripted LookupService: " + e.getLocalizedMessage(), e);
|
||||||
|
throw new ProcessException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new ScriptException("No LookupService was defined by the script.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ScriptException("Script engine is not Invocable, cannot be used for ScriptedLookupService");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
final String message = "Unable to load script: " + ex.getLocalizedMessage();
|
||||||
|
|
||||||
|
logger.error(message, ex);
|
||||||
|
results.add(new ValidationResult.Builder()
|
||||||
|
.subject("ScriptedLookupServiceValidation")
|
||||||
|
.valid(false)
|
||||||
|
.explanation("Unable to load script due to " + ex.getLocalizedMessage())
|
||||||
|
.input(scriptingComponentHelper.getScriptPath())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the updated validation results
|
||||||
|
validationResults.set(results);
|
||||||
|
|
||||||
|
// return whether there was any issues loading the configured script
|
||||||
|
return results.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -38,6 +38,8 @@ import org.apache.nifi.processor.ProcessSessionFactory;
|
||||||
import org.apache.nifi.processor.Relationship;
|
import org.apache.nifi.processor.Relationship;
|
||||||
import org.apache.nifi.processor.exception.ProcessException;
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
import org.apache.nifi.processor.util.StandardValidators;
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
|
|
|
@ -41,6 +41,8 @@ import org.apache.nifi.processor.ProcessorInitializationContext;
|
||||||
import org.apache.nifi.processor.Relationship;
|
import org.apache.nifi.processor.Relationship;
|
||||||
import org.apache.nifi.processor.exception.ProcessException;
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
import org.apache.nifi.processor.util.StandardValidators;
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
|
|
||||||
import javax.script.Invocable;
|
import javax.script.Invocable;
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
|
|
|
@ -16,130 +16,19 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.record.script;
|
package org.apache.nifi.record.script;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.nifi.components.PropertyDescriptor;
|
|
||||||
import org.apache.nifi.components.ValidationContext;
|
|
||||||
import org.apache.nifi.components.ValidationResult;
|
|
||||||
import org.apache.nifi.controller.AbstractControllerService;
|
|
||||||
import org.apache.nifi.controller.ConfigurationContext;
|
|
||||||
import org.apache.nifi.logging.ComponentLog;
|
|
||||||
import org.apache.nifi.processor.exception.ProcessException;
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
import org.apache.nifi.processor.util.StandardValidators;
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentHelper;
|
import org.apache.nifi.script.AbstractScriptedControllerService;
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentUtils;
|
|
||||||
import org.apache.nifi.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract base class containing code common to the Scripted record reader/writer implementations
|
* An abstract base class containing code common to the Scripted record reader/writer implementations
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractScriptedRecordFactory<T> extends AbstractControllerService {
|
public abstract class AbstractScriptedRecordFactory<T> extends AbstractScriptedControllerService {
|
||||||
|
|
||||||
protected final AtomicReference<T> recordFactory = new AtomicReference<>();
|
protected final AtomicReference<T> recordFactory = new AtomicReference<>();
|
||||||
|
|
||||||
protected final AtomicReference<Collection<ValidationResult>> validationResults = new AtomicReference<>(new ArrayList<>());
|
|
||||||
|
|
||||||
protected final AtomicBoolean scriptNeedsReload = new AtomicBoolean(true);
|
|
||||||
|
|
||||||
protected volatile ScriptEngine scriptEngine = null;
|
|
||||||
protected volatile ScriptingComponentHelper scriptingComponentHelper = new ScriptingComponentHelper();
|
|
||||||
protected volatile ConfigurationContext configurationContext = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of property descriptors supported by this record reader. The
|
|
||||||
* list always includes properties such as script engine name, script file
|
|
||||||
* name, script body name, script arguments, and an external module path.
|
|
||||||
*
|
|
||||||
* @return a List of PropertyDescriptor objects supported by this processor
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
|
||||||
|
|
||||||
synchronized (scriptingComponentHelper.isInitialized) {
|
|
||||||
if (!scriptingComponentHelper.isInitialized.get()) {
|
|
||||||
scriptingComponentHelper.createResources();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<PropertyDescriptor> supportedPropertyDescriptors = new ArrayList<>();
|
|
||||||
supportedPropertyDescriptors.addAll(scriptingComponentHelper.getDescriptors());
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(supportedPropertyDescriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a PropertyDescriptor for the given name. This is for the user to
|
|
||||||
* be able to define their own properties which will be available as
|
|
||||||
* variables in the script
|
|
||||||
*
|
|
||||||
* @param propertyDescriptorName used to lookup if any property descriptors
|
|
||||||
* exist for that name
|
|
||||||
* @return a PropertyDescriptor object corresponding to the specified
|
|
||||||
* dynamic property name
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
|
||||||
return new PropertyDescriptor.Builder()
|
|
||||||
.name(propertyDescriptorName)
|
|
||||||
.required(false)
|
|
||||||
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
|
||||||
.expressionLanguageSupported(true)
|
|
||||||
.dynamic(true)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles changes to this processor's properties. If changes are made to
|
|
||||||
* script- or engine-related properties, the script will be reloaded.
|
|
||||||
*
|
|
||||||
* @param descriptor of the modified property
|
|
||||||
* @param oldValue non-null property value (previous)
|
|
||||||
* @param newValue the new property value or if null indicates the property
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue) {
|
|
||||||
|
|
||||||
if (ScriptingComponentUtils.SCRIPT_FILE.equals(descriptor)
|
|
||||||
|| ScriptingComponentUtils.SCRIPT_BODY.equals(descriptor)
|
|
||||||
|| ScriptingComponentUtils.MODULES.equals(descriptor)
|
|
||||||
|| scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
|
||||||
scriptNeedsReload.set(true);
|
|
||||||
// Need to reset scriptEngine if the value has changed
|
|
||||||
if (scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
|
||||||
scriptEngine = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
|
|
||||||
return scriptingComponentHelper.customValidate(validationContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onEnabled(final ConfigurationContext context) {
|
|
||||||
this.configurationContext = context;
|
|
||||||
|
|
||||||
scriptingComponentHelper.setScriptEngineName(context.getProperty(scriptingComponentHelper.SCRIPT_ENGINE).getValue());
|
|
||||||
scriptingComponentHelper.setScriptPath(context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue());
|
|
||||||
scriptingComponentHelper.setScriptBody(context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue());
|
|
||||||
String modulePath = context.getProperty(ScriptingComponentUtils.MODULES).evaluateAttributeExpressions().getValue();
|
|
||||||
if (!StringUtils.isEmpty(modulePath)) {
|
|
||||||
scriptingComponentHelper.setModules(modulePath.split(","));
|
|
||||||
} else {
|
|
||||||
scriptingComponentHelper.setModules(new String[0]);
|
|
||||||
}
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setup() {
|
public void setup() {
|
||||||
// Create a single script engine, the Processor object is reused by each task
|
// Create a single script engine, the Processor object is reused by each task
|
||||||
if (scriptEngine == null) {
|
if (scriptEngine == null) {
|
||||||
|
@ -160,69 +49,4 @@ public abstract class AbstractScriptedRecordFactory<T> extends AbstractControlle
|
||||||
scriptNeedsReload.set(false);
|
scriptNeedsReload.set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the script located at the given path
|
|
||||||
*
|
|
||||||
* @param scriptPath the path to the script file to be loaded
|
|
||||||
* @return true if the script was loaded successfully; false otherwise
|
|
||||||
*/
|
|
||||||
private boolean reloadScriptFile(final String scriptPath) {
|
|
||||||
final Collection<ValidationResult> results = new HashSet<>();
|
|
||||||
|
|
||||||
try (final FileInputStream scriptStream = new FileInputStream(scriptPath)) {
|
|
||||||
return reloadScript(IOUtils.toString(scriptStream, Charset.defaultCharset()));
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
|
||||||
final ComponentLog logger = getLogger();
|
|
||||||
final String message = "Unable to load script: " + e;
|
|
||||||
|
|
||||||
logger.error(message, e);
|
|
||||||
results.add(new ValidationResult.Builder()
|
|
||||||
.subject("ScriptValidation")
|
|
||||||
.valid(false)
|
|
||||||
.explanation("Unable to load script due to " + e)
|
|
||||||
.input(scriptPath)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
// store the updated validation results
|
|
||||||
validationResults.set(results);
|
|
||||||
|
|
||||||
// return whether there was any issues loading the configured script
|
|
||||||
return results.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the script defined by the given string
|
|
||||||
*
|
|
||||||
* @param scriptBody the contents of the script to be loaded
|
|
||||||
* @return true if the script was loaded successfully; false otherwise
|
|
||||||
*/
|
|
||||||
private boolean reloadScriptBody(final String scriptBody) {
|
|
||||||
final Collection<ValidationResult> results = new HashSet<>();
|
|
||||||
try {
|
|
||||||
return reloadScript(scriptBody);
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
|
||||||
final ComponentLog logger = getLogger();
|
|
||||||
final String message = "Unable to load script: " + e;
|
|
||||||
|
|
||||||
logger.error(message, e);
|
|
||||||
results.add(new ValidationResult.Builder()
|
|
||||||
.subject("ScriptValidation")
|
|
||||||
.valid(false)
|
|
||||||
.explanation("Unable to load script due to " + e)
|
|
||||||
.input(scriptingComponentHelper.getScriptPath())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
// store the updated validation results
|
|
||||||
validationResults.set(results);
|
|
||||||
|
|
||||||
// return whether there was any issues loading the configured script
|
|
||||||
return results.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract boolean reloadScript(final String scriptBody);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,9 @@ import org.apache.nifi.logging.ComponentLog;
|
||||||
import org.apache.nifi.processor.exception.ProcessException;
|
import org.apache.nifi.processor.exception.ProcessException;
|
||||||
import org.apache.nifi.processor.util.StandardValidators;
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentHelper;
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentUtils;
|
|
||||||
import org.apache.nifi.reporting.AbstractReportingTask;
|
import org.apache.nifi.reporting.AbstractReportingTask;
|
||||||
import org.apache.nifi.reporting.ReportingContext;
|
import org.apache.nifi.reporting.ReportingContext;
|
||||||
import org.apache.nifi.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
import javax.script.ScriptContext;
|
import javax.script.ScriptContext;
|
||||||
|
@ -119,15 +117,8 @@ public class ScriptedReportingTask extends AbstractReportingTask {
|
||||||
*/
|
*/
|
||||||
@OnScheduled
|
@OnScheduled
|
||||||
public void setup(final ConfigurationContext context) {
|
public void setup(final ConfigurationContext context) {
|
||||||
scriptingComponentHelper.setScriptEngineName(context.getProperty(scriptingComponentHelper.SCRIPT_ENGINE).getValue());
|
scriptingComponentHelper.setupVariables(context);
|
||||||
scriptingComponentHelper.setScriptPath(context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue());
|
|
||||||
scriptingComponentHelper.setScriptBody(context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue());
|
|
||||||
String modulePath = context.getProperty(ScriptingComponentUtils.MODULES).evaluateAttributeExpressions().getValue();
|
|
||||||
if (!StringUtils.isEmpty(modulePath)) {
|
|
||||||
scriptingComponentHelper.setModules(modulePath.split(","));
|
|
||||||
} else {
|
|
||||||
scriptingComponentHelper.setModules(new String[0]);
|
|
||||||
}
|
|
||||||
// Create a script engine for each possible task
|
// Create a script engine for each possible task
|
||||||
scriptingComponentHelper.setup(1, getLogger());
|
scriptingComponentHelper.setup(1, getLogger());
|
||||||
scriptToRun = scriptingComponentHelper.getScriptBody();
|
scriptToRun = scriptingComponentHelper.getScriptBody();
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.apache.nifi.script;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
|
import org.apache.nifi.components.ValidationContext;
|
||||||
|
import org.apache.nifi.components.ValidationResult;
|
||||||
|
import org.apache.nifi.controller.AbstractControllerService;
|
||||||
|
import org.apache.nifi.controller.ConfigurationContext;
|
||||||
|
import org.apache.nifi.logging.ComponentLog;
|
||||||
|
import org.apache.nifi.processor.util.StandardValidators;
|
||||||
|
|
||||||
|
import javax.script.ScriptEngine;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class with common methods and variables for reuse among Controller Services
|
||||||
|
*/
|
||||||
|
public abstract class AbstractScriptedControllerService extends AbstractControllerService {
|
||||||
|
|
||||||
|
protected final AtomicReference<Collection<ValidationResult>> validationResults = new AtomicReference<>(new ArrayList<>());
|
||||||
|
|
||||||
|
protected final AtomicBoolean scriptNeedsReload = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
protected volatile ScriptEngine scriptEngine = null;
|
||||||
|
protected volatile ScriptingComponentHelper scriptingComponentHelper = new ScriptingComponentHelper();
|
||||||
|
protected volatile ConfigurationContext configurationContext = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of property descriptors supported by this record reader. The
|
||||||
|
* list always includes properties such as script engine name, script file
|
||||||
|
* name, script body name, script arguments, and an external module path.
|
||||||
|
*
|
||||||
|
* @return a List of PropertyDescriptor objects supported by this processor
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||||
|
|
||||||
|
synchronized (scriptingComponentHelper.isInitialized) {
|
||||||
|
if (!scriptingComponentHelper.isInitialized.get()) {
|
||||||
|
scriptingComponentHelper.createResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<PropertyDescriptor> supportedPropertyDescriptors = new ArrayList<>();
|
||||||
|
supportedPropertyDescriptors.addAll(scriptingComponentHelper.getDescriptors());
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(supportedPropertyDescriptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a PropertyDescriptor for the given name. This is for the user to
|
||||||
|
* be able to define their own properties which will be available as
|
||||||
|
* variables in the script
|
||||||
|
*
|
||||||
|
* @param propertyDescriptorName used to lookup if any property descriptors
|
||||||
|
* exist for that name
|
||||||
|
* @return a PropertyDescriptor object corresponding to the specified
|
||||||
|
* dynamic property name
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
|
||||||
|
return new PropertyDescriptor.Builder()
|
||||||
|
.name(propertyDescriptorName)
|
||||||
|
.required(false)
|
||||||
|
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
|
||||||
|
.expressionLanguageSupported(true)
|
||||||
|
.dynamic(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles changes to this processor's properties. If changes are made to
|
||||||
|
* script- or engine-related properties, the script will be reloaded.
|
||||||
|
*
|
||||||
|
* @param descriptor of the modified property
|
||||||
|
* @param oldValue non-null property value (previous)
|
||||||
|
* @param newValue the new property value or if null indicates the property
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue) {
|
||||||
|
|
||||||
|
if (ScriptingComponentUtils.SCRIPT_FILE.equals(descriptor)
|
||||||
|
|| ScriptingComponentUtils.SCRIPT_BODY.equals(descriptor)
|
||||||
|
|| ScriptingComponentUtils.MODULES.equals(descriptor)
|
||||||
|
|| scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
||||||
|
scriptNeedsReload.set(true);
|
||||||
|
// Need to reset scriptEngine if the value has changed
|
||||||
|
if (scriptingComponentHelper.SCRIPT_ENGINE.equals(descriptor)) {
|
||||||
|
scriptEngine = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
|
||||||
|
return scriptingComponentHelper.customValidate(validationContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEnabled(final ConfigurationContext context) {
|
||||||
|
this.configurationContext = context;
|
||||||
|
|
||||||
|
scriptingComponentHelper.setupVariables(context);
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public void setup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the script located at the given path
|
||||||
|
*
|
||||||
|
* @param scriptPath the path to the script file to be loaded
|
||||||
|
* @return true if the script was loaded successfully; false otherwise
|
||||||
|
*/
|
||||||
|
protected boolean reloadScriptFile(final String scriptPath) {
|
||||||
|
final Collection<ValidationResult> results = new HashSet<>();
|
||||||
|
|
||||||
|
try (final FileInputStream scriptStream = new FileInputStream(scriptPath)) {
|
||||||
|
return reloadScript(IOUtils.toString(scriptStream, Charset.defaultCharset()));
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
final String message = "Unable to load script: " + e;
|
||||||
|
|
||||||
|
logger.error(message, e);
|
||||||
|
results.add(new ValidationResult.Builder()
|
||||||
|
.subject("ScriptValidation")
|
||||||
|
.valid(false)
|
||||||
|
.explanation("Unable to load script due to " + e)
|
||||||
|
.input(scriptPath)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the updated validation results
|
||||||
|
validationResults.set(results);
|
||||||
|
|
||||||
|
// return whether there was any issues loading the configured script
|
||||||
|
return results.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the script defined by the given string
|
||||||
|
*
|
||||||
|
* @param scriptBody the contents of the script to be loaded
|
||||||
|
* @return true if the script was loaded successfully; false otherwise
|
||||||
|
*/
|
||||||
|
protected boolean reloadScriptBody(final String scriptBody) {
|
||||||
|
final Collection<ValidationResult> results = new HashSet<>();
|
||||||
|
try {
|
||||||
|
return reloadScript(scriptBody);
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
final ComponentLog logger = getLogger();
|
||||||
|
final String message = "Unable to load script: " + e;
|
||||||
|
|
||||||
|
logger.error(message, e);
|
||||||
|
results.add(new ValidationResult.Builder()
|
||||||
|
.subject("ScriptValidation")
|
||||||
|
.valid(false)
|
||||||
|
.explanation("Unable to load script due to " + e)
|
||||||
|
.input(scriptingComponentHelper.getScriptPath())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the updated validation results
|
||||||
|
validationResults.set(results);
|
||||||
|
|
||||||
|
// return whether there was any issues loading the configured script
|
||||||
|
return results.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean reloadScript(final String scriptBody);
|
||||||
|
}
|
|
@ -14,8 +14,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.controller.ConfigurationContext;
|
||||||
import org.apache.nifi.logging.ComponentLog;
|
import org.apache.nifi.logging.ComponentLog;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -48,6 +49,7 @@ import org.apache.nifi.components.PropertyDescriptor;
|
||||||
import org.apache.nifi.components.ValidationContext;
|
import org.apache.nifi.components.ValidationContext;
|
||||||
import org.apache.nifi.components.ValidationResult;
|
import org.apache.nifi.components.ValidationResult;
|
||||||
import org.apache.nifi.processor.ProcessContext;
|
import org.apache.nifi.processor.ProcessContext;
|
||||||
|
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
||||||
import org.apache.nifi.util.StringUtils;
|
import org.apache.nifi.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -281,7 +283,19 @@ public class ScriptingComponentHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupVariables(ProcessContext context) {
|
public void setupVariables(ProcessContext context) {
|
||||||
|
scriptEngineName = context.getProperty(SCRIPT_ENGINE).getValue();
|
||||||
|
scriptPath = context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue();
|
||||||
|
scriptBody = context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue();
|
||||||
|
String modulePath = context.getProperty(ScriptingComponentUtils.MODULES).evaluateAttributeExpressions().getValue();
|
||||||
|
if (!StringUtils.isEmpty(modulePath)) {
|
||||||
|
modules = modulePath.split(",");
|
||||||
|
} else {
|
||||||
|
modules = new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupVariables(ConfigurationContext context) {
|
||||||
scriptEngineName = context.getProperty(SCRIPT_ENGINE).getValue();
|
scriptEngineName = context.getProperty(SCRIPT_ENGINE).getValue();
|
||||||
scriptPath = context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue();
|
scriptPath = context.getProperty(ScriptingComponentUtils.SCRIPT_FILE).evaluateAttributeExpressions().getValue();
|
||||||
scriptBody = context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue();
|
scriptBody = context.getProperty(ScriptingComponentUtils.SCRIPT_BODY).getValue();
|
||||||
|
@ -310,7 +324,7 @@ public class ScriptingComponentHelper {
|
||||||
return factory.getScriptEngine();
|
return factory.getScriptEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
public void stop() {
|
||||||
if (engineQ != null) {
|
if (engineQ != null) {
|
||||||
engineQ.clear();
|
engineQ.clear();
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.script;
|
||||||
|
|
||||||
import org.apache.nifi.components.PropertyDescriptor;
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
import org.apache.nifi.components.Validator;
|
import org.apache.nifi.components.Validator;
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script.impl;
|
package org.apache.nifi.script.impl;
|
||||||
|
|
||||||
import org.apache.nifi.logging.ComponentLog;
|
import org.apache.nifi.logging.ComponentLog;
|
||||||
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script.impl;
|
package org.apache.nifi.script.impl;
|
||||||
|
|
||||||
import org.apache.nifi.processors.script.engine.ClojureScriptEngine;
|
import org.apache.nifi.processors.script.engine.ClojureScriptEngine;
|
||||||
|
|
||||||
|
@ -37,8 +37,10 @@ public class ClojureScriptEngineConfigurator extends AbstractModuleClassloaderCo
|
||||||
+ "[org.apache.nifi.processor.exception FlowFileAccessException FlowFileHandlingException MissingFlowFileException ProcessException]\n"
|
+ "[org.apache.nifi.processor.exception FlowFileAccessException FlowFileHandlingException MissingFlowFileException ProcessException]\n"
|
||||||
+ "[org.apache.nifi.processor.io InputStreamCallback OutputStreamCallback StreamCallback]\n"
|
+ "[org.apache.nifi.processor.io InputStreamCallback OutputStreamCallback StreamCallback]\n"
|
||||||
+ "[org.apache.nifi.processor.util FlowFileFilters StandardValidators]\n"
|
+ "[org.apache.nifi.processor.util FlowFileFilters StandardValidators]\n"
|
||||||
+ "[org.apache.nifi.processors.script ScriptingComponentHelper ScriptingComponentUtils ExecuteScript InvokeScriptedProcessor ScriptEngineConfigurator]\n"
|
+ "[org.apache.nifi.processors.script ExecuteScript InvokeScriptedProcessor ScriptEngineConfigurator]\n"
|
||||||
|
+ "[org.apache.nifi.script ScriptingComponentHelper ScriptingComponentUtils]\n"
|
||||||
+ "[org.apache.nifi.logging ComponentLog]\n"
|
+ "[org.apache.nifi.logging ComponentLog]\n"
|
||||||
|
+ "[org.apache.nifi.lookup LookupService RecordLookupService StringLookupService LookupFailureException]\n"
|
||||||
+ ")\n";
|
+ ")\n";
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script.impl;
|
package org.apache.nifi.script.impl;
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
||||||
|
@ -29,8 +29,9 @@ public class GroovyScriptEngineConfigurator extends AbstractModuleClassloaderCon
|
||||||
+ "import org.apache.nifi.processor.io.*\n"
|
+ "import org.apache.nifi.processor.io.*\n"
|
||||||
+ "import org.apache.nifi.processor.util.*\n"
|
+ "import org.apache.nifi.processor.util.*\n"
|
||||||
+ "import org.apache.nifi.processors.script.*\n"
|
+ "import org.apache.nifi.processors.script.*\n"
|
||||||
+ "import org.apache.nifi.logging.ComponentLog\n";
|
+ "import org.apache.nifi.logging.ComponentLog\n"
|
||||||
|
+ "import org.apache.nifi.script.*\n"
|
||||||
|
+ "import org.apache.nifi.lookup.*\n";
|
||||||
|
|
||||||
private ScriptEngine scriptEngine;
|
private ScriptEngine scriptEngine;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script.impl;
|
package org.apache.nifi.script.impl;
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.ScriptException;
|
import javax.script.ScriptException;
|
|
@ -14,7 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script.impl;
|
package org.apache.nifi.script.impl;
|
||||||
|
|
||||||
import org.apache.nifi.logging.ComponentLog;
|
import org.apache.nifi.logging.ComponentLog;
|
||||||
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
import org.apache.nifi.processors.script.ScriptEngineConfigurator;
|
|
@ -15,3 +15,4 @@
|
||||||
|
|
||||||
org.apache.nifi.record.script.ScriptedReader
|
org.apache.nifi.record.script.ScriptedReader
|
||||||
org.apache.nifi.record.script.ScriptedRecordSetWriter
|
org.apache.nifi.record.script.ScriptedRecordSetWriter
|
||||||
|
org.apache.nifi.lookup.script.ScriptedLookupService
|
|
@ -13,7 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
org.apache.nifi.processors.script.impl.ClojureScriptEngineConfigurator
|
org.apache.nifi.script.impl.ClojureScriptEngineConfigurator
|
||||||
org.apache.nifi.processors.script.impl.JythonScriptEngineConfigurator
|
org.apache.nifi.script.impl.JythonScriptEngineConfigurator
|
||||||
org.apache.nifi.processors.script.impl.GroovyScriptEngineConfigurator
|
org.apache.nifi.script.impl.GroovyScriptEngineConfigurator
|
||||||
org.apache.nifi.processors.script.impl.JavascriptScriptEngineConfigurator
|
org.apache.nifi.script.impl.JavascriptScriptEngineConfigurator
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.apache.nifi.lookup.script
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils
|
||||||
|
import org.apache.nifi.components.PropertyDescriptor
|
||||||
|
import org.apache.nifi.controller.ConfigurationContext
|
||||||
|
import org.apache.nifi.controller.ControllerServiceInitializationContext
|
||||||
|
import org.apache.nifi.logging.ComponentLog
|
||||||
|
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils
|
||||||
|
import org.apache.nifi.util.MockFlowFile
|
||||||
|
import org.apache.nifi.util.MockPropertyValue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.BeforeClass
|
||||||
|
import org.junit.Test
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertEquals
|
||||||
|
import static org.junit.Assert.assertFalse
|
||||||
|
import static org.junit.Assert.assertTrue
|
||||||
|
import static org.mockito.Mockito.mock
|
||||||
|
import static org.mockito.Mockito.when
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the ScriptedLookupService controller service
|
||||||
|
*/
|
||||||
|
class TestScriptedLookupService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TestScriptedLookupService)
|
||||||
|
ScriptedLookupService scriptedLookupService
|
||||||
|
def scriptingComponent
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
static void setUpOnce() throws Exception {
|
||||||
|
logger.metaClass.methodMissing = {String name, args ->
|
||||||
|
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
|
||||||
|
}
|
||||||
|
FileUtils.copyDirectory('src/test/resources' as File, 'target/test/resources' as File)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
void setUp() {
|
||||||
|
scriptedLookupService = new MockScriptedLookupService()
|
||||||
|
scriptingComponent = (AccessibleScriptingComponentHelper) scriptedLookupService
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLookupServiceGroovyScript() {
|
||||||
|
|
||||||
|
def properties = [:] as Map<PropertyDescriptor, String>
|
||||||
|
scriptedLookupService.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('Groovy'))
|
||||||
|
when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_FILE))
|
||||||
|
.thenReturn(new MockPropertyValue('target/test/resources/groovy/test_lookup_inline.groovy'))
|
||||||
|
when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_BODY))
|
||||||
|
.thenReturn(new MockPropertyValue(null))
|
||||||
|
when(configurationContext.getProperty(ScriptingComponentUtils.MODULES))
|
||||||
|
.thenReturn(new MockPropertyValue(null))
|
||||||
|
|
||||||
|
def logger = mock(ComponentLog)
|
||||||
|
def initContext = mock(ControllerServiceInitializationContext)
|
||||||
|
when(initContext.getIdentifier()).thenReturn(UUID.randomUUID().toString())
|
||||||
|
when(initContext.getLogger()).thenReturn(logger)
|
||||||
|
|
||||||
|
scriptedLookupService.initialize initContext
|
||||||
|
scriptedLookupService.onEnabled configurationContext
|
||||||
|
|
||||||
|
MockFlowFile mockFlowFile = new MockFlowFile(1L)
|
||||||
|
InputStream inStream = new ByteArrayInputStream('Flow file content not used'.bytes)
|
||||||
|
|
||||||
|
Optional opt = scriptedLookupService.lookup('Hello')
|
||||||
|
assertTrue(opt.present)
|
||||||
|
assertEquals('Hi', opt.get())
|
||||||
|
opt = scriptedLookupService.lookup('World')
|
||||||
|
assertTrue(opt.present)
|
||||||
|
assertEquals('there', opt.get())
|
||||||
|
opt = scriptedLookupService.lookup('Not There')
|
||||||
|
assertFalse(opt.present)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockScriptedLookupService extends ScriptedLookupService implements AccessibleScriptingComponentHelper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ScriptingComponentHelper getScriptingComponentHelper() {
|
||||||
|
return this.@scriptingComponentHelper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script
|
package org.apache.nifi.processors.script
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils
|
||||||
import org.apache.nifi.util.MockFlowFile
|
import org.apache.nifi.util.MockFlowFile
|
||||||
import org.apache.nifi.util.StopWatch
|
import org.apache.nifi.util.StopWatch
|
||||||
import org.apache.nifi.util.TestRunners
|
import org.apache.nifi.util.TestRunners
|
||||||
|
|
|
@ -23,8 +23,8 @@ import org.apache.nifi.controller.ControllerServiceInitializationContext
|
||||||
import org.apache.nifi.logging.ComponentLog
|
import org.apache.nifi.logging.ComponentLog
|
||||||
import org.apache.nifi.processor.util.StandardValidators
|
import org.apache.nifi.processor.util.StandardValidators
|
||||||
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentHelper
|
import org.apache.nifi.script.ScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentUtils
|
import org.apache.nifi.script.ScriptingComponentUtils
|
||||||
import org.apache.nifi.serialization.RecordReader
|
import org.apache.nifi.serialization.RecordReader
|
||||||
import org.apache.nifi.util.MockComponentLog
|
import org.apache.nifi.util.MockComponentLog
|
||||||
import org.apache.nifi.util.MockFlowFile
|
import org.apache.nifi.util.MockFlowFile
|
||||||
|
|
|
@ -22,8 +22,8 @@ import org.apache.nifi.controller.ConfigurationContext
|
||||||
import org.apache.nifi.controller.ControllerServiceInitializationContext
|
import org.apache.nifi.controller.ControllerServiceInitializationContext
|
||||||
import org.apache.nifi.logging.ComponentLog
|
import org.apache.nifi.logging.ComponentLog
|
||||||
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentHelper
|
import org.apache.nifi.script.ScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentUtils
|
import org.apache.nifi.script.ScriptingComponentUtils
|
||||||
import org.apache.nifi.serialization.RecordSetWriter
|
import org.apache.nifi.serialization.RecordSetWriter
|
||||||
import org.apache.nifi.serialization.SimpleRecordSchema
|
import org.apache.nifi.serialization.SimpleRecordSchema
|
||||||
import org.apache.nifi.serialization.record.MapRecord
|
import org.apache.nifi.serialization.record.MapRecord
|
||||||
|
|
|
@ -22,8 +22,8 @@ import org.apache.nifi.components.PropertyValue
|
||||||
import org.apache.nifi.controller.ConfigurationContext
|
import org.apache.nifi.controller.ConfigurationContext
|
||||||
import org.apache.nifi.logging.ComponentLog
|
import org.apache.nifi.logging.ComponentLog
|
||||||
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
import org.apache.nifi.processors.script.AccessibleScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentHelper
|
import org.apache.nifi.script.ScriptingComponentHelper
|
||||||
import org.apache.nifi.processors.script.ScriptingComponentUtils
|
import org.apache.nifi.script.ScriptingComponentUtils
|
||||||
import org.apache.nifi.provenance.ProvenanceEventBuilder
|
import org.apache.nifi.provenance.ProvenanceEventBuilder
|
||||||
import org.apache.nifi.provenance.ProvenanceEventRecord
|
import org.apache.nifi.provenance.ProvenanceEventRecord
|
||||||
import org.apache.nifi.provenance.ProvenanceEventRepository
|
import org.apache.nifi.provenance.ProvenanceEventRepository
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for retrieving the scripting component helper for a scripting processor. Aids in testing (for setting the Script Engine descriptor, for example).
|
* An interface for retrieving the scripting component helper for a scripting processor. Aids in testing (for setting the Script Engine descriptor, for example).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentHelper;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
import org.apache.nifi.util.TestRunners;
|
import org.apache.nifi.util.TestRunners;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
import org.apache.nifi.util.TestRunners;
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
import org.apache.nifi.util.TestRunners;
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
import org.apache.nifi.util.TestRunners;
|
import org.apache.nifi.util.TestRunners;
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
import org.apache.nifi.components.PropertyDescriptor;
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
import org.apache.nifi.processor.Relationship;
|
import org.apache.nifi.processor.Relationship;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.MockProcessContext;
|
import org.apache.nifi.util.MockProcessContext;
|
||||||
import org.apache.nifi.util.MockProcessorInitializationContext;
|
import org.apache.nifi.util.MockProcessorInitializationContext;
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
import org.apache.nifi.components.PropertyDescriptor;
|
import org.apache.nifi.components.PropertyDescriptor;
|
||||||
import org.apache.nifi.processor.Relationship;
|
import org.apache.nifi.processor.Relationship;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.MockProcessContext;
|
import org.apache.nifi.util.MockProcessContext;
|
||||||
import org.apache.nifi.util.MockProcessorInitializationContext;
|
import org.apache.nifi.util.MockProcessorInitializationContext;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.nifi.processors.script;
|
package org.apache.nifi.processors.script;
|
||||||
|
|
||||||
import org.apache.nifi.components.ValidationResult;
|
import org.apache.nifi.components.ValidationResult;
|
||||||
|
import org.apache.nifi.script.ScriptingComponentUtils;
|
||||||
import org.apache.nifi.util.MockFlowFile;
|
import org.apache.nifi.util.MockFlowFile;
|
||||||
import org.apache.nifi.util.MockProcessContext;
|
import org.apache.nifi.util.MockProcessContext;
|
||||||
import org.apache.nifi.util.TestRunner;
|
import org.apache.nifi.util.TestRunner;
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.nifi.controller.ControllerServiceInitializationContext
|
||||||
|
import org.apache.nifi.reporting.InitializationException
|
||||||
|
|
||||||
|
|
||||||
|
class GroovyLookupService implements LookupService<String> {
|
||||||
|
|
||||||
|
def lookupTable = [
|
||||||
|
'Hello': 'Hi',
|
||||||
|
'World': 'there'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Optional<String> lookup(String key) {
|
||||||
|
Optional.ofNullable(lookupTable[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Class<?> getValueType() {
|
||||||
|
return String
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void initialize(ControllerServiceInitializationContext context) throws InitializationException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Collection<ValidationResult> validate(ValidationContext context) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
PropertyDescriptor getPropertyDescriptor(String name) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onPropertyModified(PropertyDescriptor descriptor, String oldValue, String newValue) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
List<PropertyDescriptor> getPropertyDescriptors() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getIdentifier() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupService = new GroovyLookupService()
|
Loading…
Reference in New Issue