/** * Gets the bundle with the given coordinate. * * @param bundleCoordinate the coordinate of the bundle to find * @return the bundle with the coordinate, or an empty optional */ private Optional<Bundle> getBundle(final BundleCoordinate bundleCoordinate) { return initContext.bundles.values().stream() .filter(b -> b.getBundleDetails().getCoordinate().equals(bundleCoordinate)) .findFirst(); }
@Override public void discoverExtensions(final Set<Bundle> narBundles) { // get the current context class loader ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); // consider each nar class loader for (final Bundle bundle : narBundles) { // Must set the context class loader to the nar classloader itself // so that static initialization techniques that depend on the context class loader will work properly final ClassLoader ncl = bundle.getClassLoader(); Thread.currentThread().setContextClassLoader(ncl); loadExtensions(bundle); // Create a look-up from coordinate to bundle bundleCoordinateBundleLookup.put(bundle.getBundleDetails().getCoordinate(), bundle); } // restore the current context class loader if appropriate if (currentContextClassLoader != null) { Thread.currentThread().setContextClassLoader(currentContextClassLoader); } }
final BundleDetails bundleDetail = bundle.getBundleDetails(); final String bundleId = bundleDetail.getCoordinate().getId(); final Set<BundleCoordinate> coordinates = bundleIdToCoordinatesLookup.computeIfAbsent(bundleId, (id) -> new HashSet<>()); final Bundle bundle = new Bundle(bundleDetail, bundleClassLoader); loadedBundles.add(bundle); additionalBundleDetailsIter.remove();
private static StateProvider instantiateStateProvider(final ExtensionManager extensionManager, final String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException { final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); try { final List<Bundle> bundles = extensionManager.getBundles(type); if (bundles.size() == 0) { throw new IllegalStateException(String.format("The specified class '%s' is not known to this nifi.", type)); } if (bundles.size() > 1) { throw new IllegalStateException(String.format("Multiple bundles found for the specified class '%s', only one is allowed.", type)); } final Bundle bundle = bundles.get(0); final ClassLoader detectedClassLoaderForType = bundle.getClassLoader(); final Class<?> rawClass = Class.forName(type, true, detectedClassLoaderForType); Thread.currentThread().setContextClassLoader(detectedClassLoaderForType); final Class<? extends StateProvider> mgrClass = rawClass.asSubclass(StateProvider.class); return withNarClassLoader(mgrClass.newInstance()); } finally { if (ctxClassLoader != null) { Thread.currentThread().setContextClassLoader(ctxClassLoader); } } }
/** * Returns a bundle representing the system class loader. * * @param niFiProperties a NiFiProperties instance which will be used to obtain the default NAR library path, * which will become the working directory of the returned bundle * @return a bundle for the system class loader */ public static Bundle create(final NiFiProperties niFiProperties) { final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); final String narLibraryDirectory = niFiProperties.getProperty(NiFiProperties.NAR_LIBRARY_DIRECTORY); if (StringUtils.isBlank(narLibraryDirectory)) { throw new IllegalStateException("Unable to create system bundle because " + NiFiProperties.NAR_LIBRARY_DIRECTORY + " was null or empty"); } final BundleDetails systemBundleDetails = new BundleDetails.Builder() .workingDir(new File(narLibraryDirectory)) .coordinate(SYSTEM_BUNDLE_COORDINATE) .build(); return new Bundle(systemBundleDetails, systemClassLoader); } }
public FlowFilePrioritizer createPrioritizer(final String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException { FlowFilePrioritizer prioritizer; final ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader(); try { final List<Bundle> prioritizerBundles = flowController.getExtensionManager().getBundles(type); if (prioritizerBundles.size() == 0) { throw new IllegalStateException(String.format("The specified class '%s' is not known to this nifi.", type)); } if (prioritizerBundles.size() > 1) { throw new IllegalStateException(String.format("Multiple bundles found for the specified class '%s', only one is allowed.", type)); } final Bundle bundle = prioritizerBundles.get(0); final ClassLoader detectedClassLoaderForType = bundle.getClassLoader(); final Class<?> rawClass = Class.forName(type, true, detectedClassLoaderForType); Thread.currentThread().setContextClassLoader(detectedClassLoaderForType); final Class<? extends FlowFilePrioritizer> prioritizerClass = rawClass.asSubclass(FlowFilePrioritizer.class); final Object processorObj = prioritizerClass.newInstance(); prioritizer = prioritizerClass.cast(processorObj); return prioritizer; } finally { if (ctxClassLoader != null) { Thread.currentThread().setContextClassLoader(ctxClassLoader); } } }
/** * Returns a bundle representing the system class loader. * * @param niFiProperties a NiFiProperties instance which will be used to obtain the default NAR library path, * which will become the working directory of the returned bundle * @return a bundle for the system class loader */ public static Bundle create(final NiFiProperties niFiProperties) { final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); final String narLibraryDirectory = niFiProperties.getProperty(NiFiProperties.NAR_LIBRARY_DIRECTORY); if (StringUtils.isBlank(narLibraryDirectory)) { throw new IllegalStateException("Unable to create system bundle because " + NiFiProperties.NAR_LIBRARY_DIRECTORY + " was null or empty"); } final BundleDetails systemBundleDetails = new BundleDetails.Builder() .workingDir(new File(narLibraryDirectory)) .coordinate(SYSTEM_BUNDLE_COORDINATE) .build(); return new Bundle(systemBundleDetails, systemClassLoader); } }
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(); } }
final boolean isReportingTask = ReportingTask.class.equals(entry.getKey()); final ServiceLoader<?> serviceLoader = ServiceLoader.load(entry.getKey(), bundle.getClassLoader()); for (final Object o : serviceLoader) { initializeTempComponent(configurableComponent); final String cacheKey = getClassBundleKey(o.getClass().getCanonicalName(), bundle.getBundleDetails().getCoordinate()); tempComponentLookup.put(cacheKey, (ConfigurableComponent)o); boolean registerExtension = bundle.getClassLoader().equals(o.getClass().getClassLoader()); if (canReferenceControllerService && !checkControllerServiceReferenceEligibility((ConfigurableComponent) o, bundle.getClassLoader())) { registerExtension = false; logger.error(String.format( classLoaderBundleLookup.put(bundle.getClassLoader(), bundle);
/** * Creates a Closeable object that can be used to to switch to current class * loader to the framework class loader and will automatically set the * ClassLoader back to the previous class loader when closed * * @return a NarCloseable */ public static NarCloseable withFrameworkNar() { final ClassLoader frameworkClassLoader; try { frameworkClassLoader = NarClassLoadersHolder.getInstance().getFrameworkBundle().getClassLoader(); } catch (final Exception e) { // This should never happen in a running instance, but it will occur in unit tests logger.error("Unable to access Framework ClassLoader due to " + e + ". Will continue without changing ClassLoaders."); if (logger.isDebugEnabled()) { logger.error("", e); } return new NarCloseable(null); } final ClassLoader current = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(frameworkClassLoader); return new NarCloseable(current); }
narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, jettyClassLoader)); narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), jettyClassLoader); narDetailsIter.remove(); narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, bundleClassLoader)); narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), narClassLoader); narDetailsIter.remove(); .filter(b -> b.getBundleDetails().getCoordinate().getId().equals(FRAMEWORK_NAR_ID)) .findFirst().orElse(null); .filter(b -> b.getBundleDetails().getCoordinate().getId().equals(JETTY_NAR_ID)) .findFirst().orElse(null);
/** * Returns a bundle representing the system class loader. * * @param niFiProperties a NiFiProperties instance which will be used to obtain the default NAR library path, * which will become the working directory of the returned bundle * @return a bundle for the system class loader */ public static Bundle create(final NiFiProperties niFiProperties) { final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); final String narLibraryDirectory = niFiProperties.getProperty(NiFiProperties.NAR_LIBRARY_DIRECTORY); if (StringUtils.isBlank(narLibraryDirectory)) { throw new IllegalStateException("Unable to create system bundle because " + NiFiProperties.NAR_LIBRARY_DIRECTORY + " was null or empty"); } final BundleDetails systemBundleDetails = new BundleDetails.Builder() .workingDir(new File(narLibraryDirectory)) .coordinate(SYSTEM_BUNDLE_COORDINATE) .build(); return new Bundle(systemBundleDetails, systemClassLoader); } }
private Map<File, Bundle> findWars(final Set<Bundle> bundles) { final Map<File, Bundle> wars = new HashMap<>(); // consider each nar working directory bundles.forEach(bundle -> { final BundleDetails details = bundle.getBundleDetails(); final File narDependencies = new File(details.getWorkingDirectory(), "NAR-INF/bundled-dependencies"); if (narDependencies.isDirectory()) { // list the wars from this nar final File[] narDependencyDirs = narDependencies.listFiles(WAR_FILTER); if (narDependencyDirs == null) { throw new IllegalStateException(String.format("Unable to access working directory for NAR dependencies in: %s", narDependencies.getAbsolutePath())); } // add each war for (final File war : narDependencyDirs) { wars.put(war, bundle); } } }); return wars; }
final ClassLoader bundleClassLoader = bundle.getClassLoader(); final String key = getClassBundleKey(classType, bundle.getBundleDetails().getCoordinate()); logger.debug("Including ClassLoader resources from {} for component {}", new Object[] {bundle.getBundleDetails(), instanceIdentifier}); final ConfigurableComponent component = getTempComponent(classType, bundle.getBundleDetails().getCoordinate()); final Set<BundleCoordinate> reachableApiBundles = findReachableApiBundles(component); if (ancestorNarBundle == null || reachableApiBundles.contains(ancestorNarBundle.getBundleDetails().getCoordinate()) || ancestorNarBundle.getBundleDetails().getCoordinate().getId().equals(NarClassLoaders.JETTY_NAR_ID)) { break;
final ClassLoader detectedClassLoaderForType = bundle.getClassLoader(); final Class<?> rawClass = Class.forName(implementationClassName, true, detectedClassLoaderForType);
narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, bundleClassLoader)); narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), narClassLoader); narDetailsIter.remove(); .filter(b -> b.getBundleDetails().getCoordinate().getId().equals(FRAMEWORK_NAR_ID)) .findFirst().orElse(null);
@Override public void logClassLoaderMapping() { final StringBuilder builder = new StringBuilder(); builder.append("Extension Type Mapping to Bundle:"); for (final Map.Entry<Class, Set<Class>> entry : definitionMap.entrySet()) { builder.append("\n\t=== ").append(entry.getKey().getSimpleName()).append(" Type ==="); for (final Class type : entry.getValue()) { final List<Bundle> bundles = classNameBundleLookup.containsKey(type.getName()) ? classNameBundleLookup.get(type.getName()) : Collections.emptyList(); builder.append("\n\t").append(type.getName()); for (final Bundle bundle : bundles) { final String coordinate = bundle.getBundleDetails().getCoordinate().getCoordinate(); final String workingDir = bundle.getBundleDetails().getWorkingDirectory().getPath(); builder.append("\n\t\t").append(coordinate).append(" || ").append(workingDir); } } builder.append("\n\t=== End ").append(entry.getKey().getSimpleName()).append(" types ==="); } logger.info(builder.toString()); } }
/** * Loads all FlowFileProcessor, FlowFileComparator, ReportingTask class types that can be found on the bootstrap classloader and by creating classloaders for all NARs found within the classpath. * * @param narBundles the bundles to scan through in search of extensions */ public static void discoverExtensions(final Bundle systemBundle, final Set<Bundle> narBundles) { // get the current context class loader ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader(); // load the system bundle first so that any extensions found in JARs directly in lib will be registered as // being from the system bundle and not from all the other NARs loadExtensions(systemBundle); bundleCoordinateBundleLookup.put(systemBundle.getBundleDetails().getCoordinate(), systemBundle); // consider each nar class loader for (final Bundle bundle : narBundles) { // Must set the context class loader to the nar classloader itself // so that static initialization techniques that depend on the context class loader will work properly final ClassLoader ncl = bundle.getClassLoader(); Thread.currentThread().setContextClassLoader(ncl); loadExtensions(bundle); // Create a look-up from coordinate to bundle bundleCoordinateBundleLookup.put(bundle.getBundleDetails().getCoordinate(), bundle); } // restore the current context class loader if appropriate if (currentContextClassLoader != null) { Thread.currentThread().setContextClassLoader(currentContextClassLoader); } }
final ClassLoader loginIdentityProviderClassLoader = loginIdentityProviderBundle.getClassLoader();
narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, bundleClassLoader)); narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), narClassLoader); narDetailsIter.remove(); .filter(b -> b.getBundleDetails().getCoordinate().getId().equals(FRAMEWORK_NAR_ID)) .findFirst().orElse(null);