use of org.apache.nifi.bundle.BundleCoordinate in project nifi by apache.
the class ReportingTaskAuditor method extractConfiguredPropertyValues.
/**
* Extracts the values for the configured properties from the specified ReportingTask.
*
* @param reportingTask task
* @param reportingTaskDTO dto
* @return properties of task
*/
private Map<String, String> extractConfiguredPropertyValues(ReportingTaskNode reportingTask, ReportingTaskDTO reportingTaskDTO) {
Map<String, String> values = new HashMap<>();
if (reportingTaskDTO.getName() != null) {
values.put(NAME, reportingTask.getName());
}
if (reportingTaskDTO.getAnnotationData() != null) {
values.put(ANNOTATION_DATA, reportingTask.getAnnotationData());
}
if (reportingTaskDTO.getBundle() != null) {
final BundleCoordinate bundle = reportingTask.getBundleCoordinate();
values.put(EXTENSION_VERSION, formatExtensionVersion(reportingTask.getComponentType(), bundle));
}
if (reportingTaskDTO.getProperties() != null) {
// for each property specified, extract its configured value
Map<String, String> properties = reportingTaskDTO.getProperties();
Map<PropertyDescriptor, String> configuredProperties = reportingTask.getProperties();
for (String propertyName : properties.keySet()) {
// build a descriptor for getting the configured value
PropertyDescriptor propertyDescriptor = new PropertyDescriptor.Builder().name(propertyName).build();
String configuredPropertyValue = configuredProperties.get(propertyDescriptor);
// if the configured value couldn't be found, use the default value from the actual descriptor
if (configuredPropertyValue == null) {
propertyDescriptor = locatePropertyDescriptor(configuredProperties.keySet(), propertyDescriptor);
configuredPropertyValue = propertyDescriptor.getDefaultValue();
}
values.put(propertyName, configuredPropertyValue);
}
}
return values;
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi by apache.
the class ExtensionManager method findReachableApiBundles.
/**
* Find the bundle coordinates for any service APIs that are referenced by this component and not part of the same bundle.
*
* @param component the component being instantiated
*/
protected static Set<BundleCoordinate> findReachableApiBundles(final ConfigurableComponent component) {
final Set<BundleCoordinate> reachableApiBundles = new HashSet<>();
try (final NarCloseable closeable = NarCloseable.withComponentNarLoader(component.getClass().getClassLoader())) {
final List<PropertyDescriptor> descriptors = component.getPropertyDescriptors();
if (descriptors != null && !descriptors.isEmpty()) {
for (final PropertyDescriptor descriptor : descriptors) {
final Class<? extends ControllerService> serviceApi = descriptor.getControllerServiceDefinition();
if (serviceApi != null && !component.getClass().getClassLoader().equals(serviceApi.getClassLoader())) {
final Bundle apiBundle = classLoaderBundleLookup.get(serviceApi.getClassLoader());
reachableApiBundles.add(apiBundle.getBundleDetails().getCoordinate());
}
}
}
}
return reachableApiBundles;
}
use of org.apache.nifi.bundle.BundleCoordinate 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.bundle.BundleCoordinate in project nifi by apache.
the class ExtensionManager method registerServiceClass.
/**
* Registers extension for the specified type from the specified Bundle.
*
* @param type the extension type
* @param classNameBundleMap mapping of classname to Bundle
* @param bundle the Bundle being mapped to
* @param classes to map to this classloader but which come from its ancestors
*/
private static void registerServiceClass(final Class<?> type, final Map<String, List<Bundle>> classNameBundleMap, final Bundle bundle, final Set<Class> classes) {
final String className = type.getName();
// get the bundles that have already been registered for the class name
List<Bundle> registeredBundles = classNameBundleMap.get(className);
if (registeredBundles == null) {
registeredBundles = new ArrayList<>();
classNameBundleMap.put(className, registeredBundles);
}
boolean alreadyRegistered = false;
for (final Bundle registeredBundle : registeredBundles) {
final BundleCoordinate registeredCoordinate = registeredBundle.getBundleDetails().getCoordinate();
// if the incoming bundle has the same coordinate as one of the registered bundles then consider it already registered
if (registeredCoordinate.equals(bundle.getBundleDetails().getCoordinate())) {
alreadyRegistered = true;
break;
}
// fail registration because we don't support multiple versions of any other types
if (!multipleVersionsAllowed(type)) {
throw new IllegalStateException("Attempt was made to load " + className + " from " + bundle.getBundleDetails().getCoordinate().getCoordinate() + " but that class name is already loaded/registered from " + registeredBundle.getBundleDetails().getCoordinate() + " and multiple versions are not supported for this type");
}
}
// if none of the above was true then register the new bundle
if (!alreadyRegistered) {
registeredBundles.add(bundle);
classes.add(type);
if (type.isAnnotationPresent(RequiresInstanceClassLoading.class)) {
final String cacheKey = getClassBundleKey(className, bundle.getBundleDetails().getCoordinate());
requiresInstanceClassLoading.put(cacheKey, type);
}
}
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi by apache.
the class StandardFlowSynchronizer method getOrCreateReportingTask.
private ReportingTaskNode getOrCreateReportingTask(final FlowController controller, final ReportingTaskDTO dto, final boolean controllerInitialized, final boolean existingFlowEmpty) throws ReportingTaskInstantiationException {
// create a new reporting task node when the controller is not initialized or the flow is empty
if (!controllerInitialized || existingFlowEmpty) {
BundleCoordinate coordinate;
try {
coordinate = BundleUtils.getCompatibleBundle(dto.getType(), dto.getBundle());
} catch (final IllegalStateException e) {
final BundleDTO bundleDTO = dto.getBundle();
if (bundleDTO == null) {
coordinate = BundleCoordinate.UNKNOWN_COORDINATE;
} else {
coordinate = new BundleCoordinate(bundleDTO.getGroup(), bundleDTO.getArtifact(), bundleDTO.getVersion());
}
}
final ReportingTaskNode reportingTask = controller.createReportingTask(dto.getType(), dto.getId(), coordinate, false);
reportingTask.setName(dto.getName());
reportingTask.setComments(dto.getComments());
reportingTask.setSchedulingPeriod(dto.getSchedulingPeriod());
reportingTask.setSchedulingStrategy(SchedulingStrategy.valueOf(dto.getSchedulingStrategy()));
reportingTask.setAnnotationData(dto.getAnnotationData());
reportingTask.setProperties(dto.getProperties());
final ComponentLog componentLog = new SimpleProcessLogger(dto.getId(), reportingTask.getReportingTask());
final ReportingInitializationContext config = new StandardReportingInitializationContext(dto.getId(), dto.getName(), SchedulingStrategy.valueOf(dto.getSchedulingStrategy()), dto.getSchedulingPeriod(), componentLog, controller, nifiProperties, controller);
try {
reportingTask.getReportingTask().initialize(config);
} catch (final InitializationException ie) {
throw new ReportingTaskInstantiationException("Failed to initialize reporting task of type " + dto.getType(), ie);
}
return reportingTask;
} else {
// otherwise return the existing reporting task node
return controller.getReportingTaskNode(dto.getId());
}
}
Aggregations