use of org.apache.nifi.components.ConfigurableComponent in project nifi-minifi by apache.
the class ExtensionManager method createInstanceClassLoader.
/**
* Determines the effective ClassLoader for the instance of the given type.
*
* @param classType the type of class to lookup the ClassLoader for
* @param instanceIdentifier the identifier of the specific instance of the classType to look up the ClassLoader for
* @param bundle the bundle where the classType exists
* @param additionalUrls additional URLs to add to the instance class loader
* @return the ClassLoader for the given instance of the given type, or null if the type is not a detected extension type
*/
public static InstanceClassLoader createInstanceClassLoader(final String classType, final String instanceIdentifier, final Bundle bundle, final Set<URL> additionalUrls) {
if (StringUtils.isEmpty(classType)) {
throw new IllegalArgumentException("Class-Type is required");
}
if (StringUtils.isEmpty(instanceIdentifier)) {
throw new IllegalArgumentException("Instance Identifier is required");
}
if (bundle == null) {
throw new IllegalArgumentException("Bundle is required");
}
// If the class is annotated with @RequiresInstanceClassLoading and the registered ClassLoader is a URLClassLoader
// then make a new InstanceClassLoader that is a full copy of the NAR Class Loader, otherwise create an empty
// InstanceClassLoader that has the NAR ClassLoader as a parent
InstanceClassLoader instanceClassLoader;
final ClassLoader bundleClassLoader = bundle.getClassLoader();
final String key = getClassBundleKey(classType, bundle.getBundleDetails().getCoordinate());
if (requiresInstanceClassLoading.containsKey(key) && bundleClassLoader instanceof NarClassLoader) {
final Class<?> type = requiresInstanceClassLoading.get(key);
final RequiresInstanceClassLoading requiresInstanceClassLoading = type.getAnnotation(RequiresInstanceClassLoading.class);
final NarClassLoader narBundleClassLoader = (NarClassLoader) bundleClassLoader;
logger.debug("Including ClassLoader resources from {} for component {}", new Object[] { bundle.getBundleDetails(), instanceIdentifier });
final Set<URL> instanceUrls = new LinkedHashSet<>();
for (final URL url : narBundleClassLoader.getURLs()) {
instanceUrls.add(url);
}
ClassLoader ancestorClassLoader = narBundleClassLoader.getParent();
if (requiresInstanceClassLoading.cloneAncestorResources()) {
final ConfigurableComponent component = getTempComponent(classType, bundle.getBundleDetails().getCoordinate());
final Set<BundleCoordinate> reachableApiBundles = findReachableApiBundles(component);
while (ancestorClassLoader != null && ancestorClassLoader instanceof NarClassLoader) {
final Bundle ancestorNarBundle = classLoaderBundleLookup.get(ancestorClassLoader);
// stop including ancestor resources when we reach one of the APIs
if (ancestorNarBundle == null || reachableApiBundles.contains(ancestorNarBundle.getBundleDetails().getCoordinate())) {
break;
}
final NarClassLoader ancestorNarClassLoader = (NarClassLoader) ancestorClassLoader;
for (final URL url : ancestorNarClassLoader.getURLs()) {
instanceUrls.add(url);
}
ancestorClassLoader = ancestorNarClassLoader.getParent();
}
}
instanceClassLoader = new InstanceClassLoader(instanceIdentifier, classType, instanceUrls, additionalUrls, ancestorClassLoader);
} else {
instanceClassLoader = new InstanceClassLoader(instanceIdentifier, classType, Collections.emptySet(), additionalUrls, bundleClassLoader);
}
if (logger.isTraceEnabled()) {
for (URL url : instanceClassLoader.getURLs()) {
logger.trace("URL resource {} for {}...", new Object[] { url.toExternalForm(), instanceIdentifier });
}
}
instanceClassloaderLookup.put(instanceIdentifier, instanceClassLoader);
return instanceClassLoader;
}
use of org.apache.nifi.components.ConfigurableComponent in project nifi by apache.
the class StandardNiFiServiceFacade method ensureDefaultPropertyValuesArePopulated.
/**
* Ensures default values are populated for all components in this snippet. This is necessary to handle old templates without default values
* and when existing properties have default values introduced.
*
* @param snippet snippet
*/
private void ensureDefaultPropertyValuesArePopulated(final FlowSnippetDTO snippet) {
if (snippet != null) {
if (snippet.getControllerServices() != null) {
snippet.getControllerServices().forEach(dto -> {
if (dto.getProperties() == null) {
dto.setProperties(new LinkedHashMap<>());
}
try {
final ConfigurableComponent configurableComponent = controllerFacade.getTemporaryComponent(dto.getType(), dto.getBundle());
configurableComponent.getPropertyDescriptors().forEach(descriptor -> {
if (dto.getProperties().get(descriptor.getName()) == null) {
dto.getProperties().put(descriptor.getName(), descriptor.getDefaultValue());
}
});
} catch (final Exception e) {
logger.warn(String.format("Unable to create ControllerService of type %s to populate default values.", dto.getType()));
}
});
}
if (snippet.getProcessors() != null) {
snippet.getProcessors().forEach(dto -> {
if (dto.getConfig() == null) {
dto.setConfig(new ProcessorConfigDTO());
}
final ProcessorConfigDTO config = dto.getConfig();
if (config.getProperties() == null) {
config.setProperties(new LinkedHashMap<>());
}
try {
final ConfigurableComponent configurableComponent = controllerFacade.getTemporaryComponent(dto.getType(), dto.getBundle());
configurableComponent.getPropertyDescriptors().forEach(descriptor -> {
if (config.getProperties().get(descriptor.getName()) == null) {
config.getProperties().put(descriptor.getName(), descriptor.getDefaultValue());
}
});
} catch (final Exception e) {
logger.warn(String.format("Unable to create Processor of type %s to populate default values.", dto.getType()));
}
});
}
if (snippet.getProcessGroups() != null) {
snippet.getProcessGroups().forEach(processGroup -> {
ensureDefaultPropertyValuesArePopulated(processGroup.getContents());
});
}
}
}
use of org.apache.nifi.components.ConfigurableComponent in project nifi by apache.
the class ExtensionManager method loadExtensions.
/**
* Loads extensions from the specified bundle.
*
* @param bundle from which to load extensions
*/
@SuppressWarnings("unchecked")
private static void loadExtensions(final Bundle bundle) {
for (final Map.Entry<Class, Set<Class>> entry : definitionMap.entrySet()) {
final boolean isControllerService = ControllerService.class.equals(entry.getKey());
final boolean isProcessor = Processor.class.equals(entry.getKey());
final boolean isReportingTask = ReportingTask.class.equals(entry.getKey());
final ServiceLoader<?> serviceLoader = ServiceLoader.load(entry.getKey(), bundle.getClassLoader());
for (final Object o : serviceLoader) {
// create a cache of temp ConfigurableComponent instances, the initialize here has to happen before the checks below
if ((isControllerService || isProcessor || isReportingTask) && o instanceof ConfigurableComponent) {
final ConfigurableComponent configurableComponent = (ConfigurableComponent) o;
initializeTempComponent(configurableComponent);
final String cacheKey = getClassBundleKey(o.getClass().getCanonicalName(), bundle.getBundleDetails().getCoordinate());
tempComponentLookup.put(cacheKey, (ConfigurableComponent) o);
}
// only consider extensions discovered directly in this bundle
boolean registerExtension = bundle.getClassLoader().equals(o.getClass().getClassLoader());
if (registerExtension) {
final Class extensionType = o.getClass();
if (isControllerService && !checkControllerServiceEligibility(extensionType)) {
registerExtension = false;
logger.error(String.format("Skipping Controller Service %s because it is bundled with its supporting APIs and requires instance class loading.", extensionType.getName()));
}
final boolean canReferenceControllerService = (isControllerService || isProcessor || isReportingTask) && o instanceof ConfigurableComponent;
if (canReferenceControllerService && !checkControllerServiceReferenceEligibility((ConfigurableComponent) o, bundle.getClassLoader())) {
registerExtension = false;
logger.error(String.format("Skipping component %s because it is bundled with its referenced Controller Service APIs and requires instance class loading.", extensionType.getName()));
}
if (registerExtension) {
registerServiceClass(o.getClass(), classNameBundleLookup, bundle, entry.getValue());
}
}
}
classLoaderBundleLookup.put(bundle.getClassLoader(), bundle);
}
}
use of org.apache.nifi.components.ConfigurableComponent in project nifi by apache.
the class ExtensionManager method createInstanceClassLoader.
/**
* Determines the effective ClassLoader for the instance of the given type.
*
* @param classType the type of class to lookup the ClassLoader for
* @param instanceIdentifier the identifier of the specific instance of the classType to look up the ClassLoader for
* @param bundle the bundle where the classType exists
* @param additionalUrls additional URLs to add to the instance class loader
* @return the ClassLoader for the given instance of the given type, or null if the type is not a detected extension type
*/
public static InstanceClassLoader createInstanceClassLoader(final String classType, final String instanceIdentifier, final Bundle bundle, final Set<URL> additionalUrls) {
if (StringUtils.isEmpty(classType)) {
throw new IllegalArgumentException("Class-Type is required");
}
if (StringUtils.isEmpty(instanceIdentifier)) {
throw new IllegalArgumentException("Instance Identifier is required");
}
if (bundle == null) {
throw new IllegalArgumentException("Bundle is required");
}
// If the class is annotated with @RequiresInstanceClassLoading and the registered ClassLoader is a URLClassLoader
// then make a new InstanceClassLoader that is a full copy of the NAR Class Loader, otherwise create an empty
// InstanceClassLoader that has the NAR ClassLoader as a parent
InstanceClassLoader instanceClassLoader;
final ClassLoader bundleClassLoader = bundle.getClassLoader();
final String key = getClassBundleKey(classType, bundle.getBundleDetails().getCoordinate());
if (requiresInstanceClassLoading.containsKey(key) && bundleClassLoader instanceof NarClassLoader) {
final Class<?> type = requiresInstanceClassLoading.get(key);
final RequiresInstanceClassLoading requiresInstanceClassLoading = type.getAnnotation(RequiresInstanceClassLoading.class);
final NarClassLoader narBundleClassLoader = (NarClassLoader) bundleClassLoader;
logger.debug("Including ClassLoader resources from {} for component {}", new Object[] { bundle.getBundleDetails(), instanceIdentifier });
final Set<URL> instanceUrls = new LinkedHashSet<>();
for (final URL url : narBundleClassLoader.getURLs()) {
instanceUrls.add(url);
}
ClassLoader ancestorClassLoader = narBundleClassLoader.getParent();
if (requiresInstanceClassLoading.cloneAncestorResources()) {
final ConfigurableComponent component = getTempComponent(classType, bundle.getBundleDetails().getCoordinate());
final Set<BundleCoordinate> reachableApiBundles = findReachableApiBundles(component);
while (ancestorClassLoader != null && ancestorClassLoader instanceof NarClassLoader) {
final Bundle ancestorNarBundle = classLoaderBundleLookup.get(ancestorClassLoader);
// stop including ancestor resources when we reach one of the APIs, or when we hit the Jetty NAR
if (ancestorNarBundle == null || reachableApiBundles.contains(ancestorNarBundle.getBundleDetails().getCoordinate()) || ancestorNarBundle.getBundleDetails().getCoordinate().getId().equals(NarClassLoaders.JETTY_NAR_ID)) {
break;
}
final NarClassLoader ancestorNarClassLoader = (NarClassLoader) ancestorClassLoader;
for (final URL url : ancestorNarClassLoader.getURLs()) {
instanceUrls.add(url);
}
ancestorClassLoader = ancestorNarClassLoader.getParent();
}
}
instanceClassLoader = new InstanceClassLoader(instanceIdentifier, classType, instanceUrls, additionalUrls, ancestorClassLoader);
} else {
instanceClassLoader = new InstanceClassLoader(instanceIdentifier, classType, Collections.emptySet(), additionalUrls, bundleClassLoader);
}
if (logger.isTraceEnabled()) {
for (URL url : instanceClassLoader.getURLs()) {
logger.trace("URL resource {} for {}...", new Object[] { url.toExternalForm(), instanceIdentifier });
}
}
instanceClassloaderLookup.put(instanceIdentifier, instanceClassLoader);
return instanceClassLoader;
}
use of org.apache.nifi.components.ConfigurableComponent in project nifi by apache.
the class FingerprintFactory method addControllerServiceFingerprint.
private void addControllerServiceFingerprint(final StringBuilder builder, final ControllerServiceDTO dto) {
builder.append(dto.getId());
builder.append(dto.getVersionedComponentId());
builder.append(dto.getType());
builder.append(dto.getName());
addBundleFingerprint(builder, dto.getBundle());
builder.append(dto.getComments());
builder.append(dto.getAnnotationData());
builder.append(dto.getState());
// get the temp instance of the ControllerService so that we know the default property values
final BundleCoordinate coordinate = getCoordinate(dto.getType(), dto.getBundle());
final ConfigurableComponent configurableComponent = ExtensionManager.getTempComponent(dto.getType(), coordinate);
if (configurableComponent == null) {
logger.warn("Unable to get ControllerService of type {}; its default properties will be fingerprinted instead of being ignored.", dto.getType());
}
addPropertiesFingerprint(builder, configurableComponent, dto.getProperties());
}
Aggregations