private static BundleCoordinate findBundleForType(final ExtensionManager extensionManager, final String type, final BundleCoordinate desiredCoordinate) { final List<Bundle> bundles = extensionManager.getBundles(type); if (bundles.isEmpty()) { throw new IllegalStateException(String.format("%s is not known to this NiFi instance.", type)); } else if (bundles.size() > 1) { if (desiredCoordinate == null) { throw new IllegalStateException(String.format("Multiple versions of %s exist.", type)); } else { throw new IllegalStateException(String.format("Multiple versions of %s exist. No exact match for %s.", type, desiredCoordinate)); } } else { return bundles.get(0).getBundleDetails().getCoordinate(); } }
private static BundleCoordinate findCompatibleBundle(final ExtensionManager extensionManager, final String type, final BundleDTO bundleDTO, final boolean allowCompatibleBundle) { final BundleCoordinate coordinate = new BundleCoordinate(bundleDTO.getGroup(), bundleDTO.getArtifact(), bundleDTO.getVersion()); final Bundle bundle = extensionManager.getBundle(coordinate); if (bundle == null) { if (allowCompatibleBundle) { return findBundleForType(extensionManager, type, coordinate); } else { throw new IllegalStateException(String.format("%s from %s is not known to this NiFi instance.", type, coordinate)); } } else { final List<BundleCoordinate> bundlesForType = extensionManager.getBundles(type).stream().map(b -> b.getBundleDetails().getCoordinate()).collect(Collectors.toList()); if (bundlesForType.contains(coordinate)) { return coordinate; } else { throw new IllegalStateException(String.format("Found bundle %s but does not support %s", coordinate, type)); } } }
/** * Sets the current thread context class loader to the specific appropriate class loader for the given * component. If the component requires per-instance class loading then the class loader will be the * specific class loader for instance with the given identifier, otherwise the class loader will be * the NARClassLoader. * * @param componentClass the component class * @param componentIdentifier the identifier of the component * @return NarCloseable with the current thread context classloader jailed to the Nar * or instance class loader of the component */ public static NarCloseable withComponentNarLoader(final ExtensionManager extensionManager, final Class componentClass, final String componentIdentifier) { final ClassLoader current = Thread.currentThread().getContextClassLoader(); ClassLoader componentClassLoader = extensionManager.getInstanceClassLoader(componentIdentifier); if (componentClassLoader == null) { componentClassLoader = componentClass.getClassLoader(); } Thread.currentThread().setContextClassLoader(componentClassLoader); return new NarCloseable(current); }
private <T extends ConfigurableComponent> LoggableComponent<T> createLoggableComponent(Class<T> nodeType) throws ClassNotFoundException, IllegalAccessException, InstantiationException { final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); try { final Bundle bundle = extensionManager.getBundle(bundleCoordinate); if (bundle == null) { throw new IllegalStateException("Unable to find bundle for coordinate " + bundleCoordinate.getCoordinate()); } final ClassLoader detectedClassLoader = extensionManager.createInstanceClassLoader(type, identifier, bundle, classpathUrls == null ? Collections.emptySet() : classpathUrls); final Class<?> rawClass = Class.forName(type, true, detectedClassLoader); Thread.currentThread().setContextClassLoader(detectedClassLoader); final Object extensionInstance = rawClass.newInstance(); final ComponentLog componentLog = new SimpleProcessLogger(identifier, extensionInstance); final TerminationAwareLogger terminationAwareLogger = new TerminationAwareLogger(componentLog); final T cast = nodeType.cast(extensionInstance); return new LoggableComponent<>(cast, bundleCoordinate, terminationAwareLogger); } finally { if (ctxClassLoader != null) { Thread.currentThread().setContextClassLoader(ctxClassLoader); } } } }
public void verifyComponentTypesInSnippet(final VersionedProcessGroup versionedFlow) { final Map<String, Set<BundleCoordinate>> processorClasses = new HashMap<>(); for (final Class<?> c : extensionManager.getExtensions(Processor.class)) { final String name = c.getName(); processorClasses.put(name, extensionManager.getBundles(name).stream().map(bundle -> bundle.getBundleDetails().getCoordinate()).collect(Collectors.toSet())); for (final Class<?> c : extensionManager.getExtensions(ControllerService.class)) { final String name = c.getName(); controllerServiceClasses.put(name, extensionManager.getBundles(name).stream().map(bundle -> bundle.getBundleDetails().getCoordinate()).collect(Collectors.toSet())); for (final Class<?> c : extensionManager.getExtensions(FlowFilePrioritizer.class)) { prioritizerClasses.add(c.getName());
@Override public void cleanUpResources() { extensionManager.removeInstanceClassLoader(reportingTaskNode.getIdentifier()); } }
/** * Gets the DocumentedTypeDTOs from the specified classes. * * @param classes classes * @param bundleGroupFilter if specified, must be member of bundle group * @param bundleArtifactFilter if specified, must be member of bundle artifact * @param typeFilter if specified, type must match * @return dtos */ public Set<DocumentedTypeDTO> fromDocumentedTypes(final Set<Class> classes, final String bundleGroupFilter, final String bundleArtifactFilter, final String typeFilter) { final Map<Class, Bundle> classBundles = new HashMap<>(); for (final Class cls : classes) { classBundles.put(cls, extensionManager.getBundle(cls.getClassLoader())); } return fromDocumentedTypes(classBundles, bundleGroupFilter, bundleArtifactFilter, typeFilter); }
@Override public ConfigurableComponent getTempComponent(String classType, BundleCoordinate bundleCoordinate) { return controllerFacade.getExtensionManager().getTempComponent(classType, bundleCoordinate); }
final ClassLoader existingInstanceClassLoader = extensionManager.getInstanceClassLoader(id); ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnRemoved.class, existingNode.getReportingTask(), existingNode.getConfigurationContext()); } finally { extensionManager.closeURLClassLoader(id, existingInstanceClassLoader);
final String bundleGroupFilter, final String bundleArtifactFilter, final String typeFilter) { final Set<Class> serviceImplementations = getExtensionManager().getExtensions(ControllerService.class); final Bundle csBundle = getExtensionManager().getBundle(bundleCoordinate); if (csBundle == null) { throw new IllegalStateException("Unable to find bundle for coordinate " + bundleCoordinate.getCoordinate()); matchingServiceImplementations.put(csClass, getExtensionManager().getBundle(csClass.getClassLoader()));
final String key = getClassBundleKey(classType, bundle.getBundleDetails().getCoordinate()); final ConfigurableComponent component = getTempComponent(classType, bundle.getBundleDetails().getCoordinate()); final Set<BundleCoordinate> reachableApiBundles = findReachableApiBundles(component);
/** * Uses the {@link ExtensionManager} to discover any {@link ControllerService} implementations that implement a specific * ControllerService API. * * @param parent the controller service API * @return a list of controller services that implement the controller service API */ private List<Class<? extends ControllerService>> lookupControllerServiceImpls( final Class<? extends ControllerService> parent) { final List<Class<? extends ControllerService>> implementations = new ArrayList<>(); // first get all ControllerService implementations final Set<Class> controllerServices = extensionManager.getExtensions(ControllerService.class); // then iterate over all controller services looking for any that is a child of the parent // ControllerService API that was passed in as a parameter for (final Class<? extends ControllerService> controllerServiceClass : controllerServices) { if (parent.isAssignableFrom(controllerServiceClass)) { implementations.add(controllerServiceClass); } } return implementations; }
/** * Removes the InstanceClassLoader for a given component. * * @param instanceIdentifier the of a component */ public static InstanceClassLoader removeInstanceClassLoader(final String instanceIdentifier) { if (instanceIdentifier == null) { return null; } final InstanceClassLoader classLoader = instanceClassloaderLookup.remove(instanceIdentifier); closeURLClassLoader(instanceIdentifier, classLoader); return classLoader; }
@Override public void cleanUpResources() { extensionManager.removeInstanceClassLoader(configurableComponent.getIdentifier()); } }
public void verifyComponentTypesInSnippet() { final Map<String, Set<BundleCoordinate>> processorClasses = new HashMap<>(); for (final Class<?> c : extensionManager.getExtensions(Processor.class)) { final String name = c.getName(); processorClasses.put(name, extensionManager.getBundles(name).stream().map(bundle -> bundle.getBundleDetails().getCoordinate()).collect(Collectors.toSet())); for (final Class<?> c : extensionManager.getExtensions(ControllerService.class)) { final String name = c.getName(); controllerServiceClasses.put(name, extensionManager.getBundles(name).stream().map(bundle -> bundle.getBundleDetails().getCoordinate()).collect(Collectors.toSet())); for (final Class<?> c : extensionManager.getExtensions(FlowFilePrioritizer.class)) { prioritizerClasses.add(c.getName());
private List<ControllerServiceAPI> mapControllerServiceApis(final ControllerServiceNode service) { final Class<?> serviceClass = service.getControllerServiceImplementation().getClass(); final Set<Class<?>> serviceApiClasses = new HashSet<>(); // get all of it's interfaces to determine the controller service api's it implements final List<Class<?>> interfaces = ClassUtils.getAllInterfaces(serviceClass); for (final Class<?> i : interfaces) { // add all controller services that's not ControllerService itself if (ControllerService.class.isAssignableFrom(i) && !ControllerService.class.equals(i)) { serviceApiClasses.add(i); } } final List<ControllerServiceAPI> serviceApis = new ArrayList<>(); for (final Class<?> serviceApiClass : serviceApiClasses) { final BundleCoordinate bundleCoordinate = extensionManager.getBundle(serviceApiClass.getClassLoader()).getBundleDetails().getCoordinate(); final ControllerServiceAPI serviceApi = new ControllerServiceAPI(); serviceApi.setType(serviceApiClass.getName()); serviceApi.setBundle(mapBundle(bundleCoordinate)); serviceApis.add(serviceApi); } return serviceApis; }
/** * Gets the cached temporary instance of the component for the given type and bundle. * * @param type type of the component * @param bundle the bundle of the component * @return the temporary component * @throws IllegalStateException if no temporary component exists for the given type and bundle */ public ConfigurableComponent getTemporaryComponent(final String type, final BundleDTO bundle) { final ExtensionManager extensionManager = getExtensionManager(); final BundleCoordinate bundleCoordinate = BundleUtils.getBundle(extensionManager, type, bundle); final ConfigurableComponent configurableComponent = extensionManager.getTempComponent(type, bundleCoordinate); if (configurableComponent == null) { throw new IllegalStateException("Unable to obtain temporary component for " + type); } return configurableComponent; }
final ClassLoader existingInstanceClassLoader = extensionManager.getInstanceClassLoader(id); extensionManager.closeURLClassLoader(id, existingInstanceClassLoader);
final String key = getClassBundleKey(classType, bundle.getBundleDetails().getCoordinate()); final ConfigurableComponent component = getTempComponent(classType, bundle.getBundleDetails().getCoordinate()); final Set<BundleCoordinate> reachableApiBundles = findReachableApiBundles(component);
@Override public List<String> getComponentTypes() { final Set<Class> procClasses = flowController.getExtensionManager().getExtensions(Processor.class); final List<String> componentTypes = new ArrayList<>(procClasses.size() + 2); componentTypes.add(ProvenanceEventRecord.REMOTE_INPUT_PORT_TYPE); componentTypes.add(ProvenanceEventRecord.REMOTE_OUTPUT_PORT_TYPE); procClasses.stream() .map(Class::getSimpleName) .forEach(componentTypes::add); return componentTypes; }