use of org.apache.nifi.bundle.BundleCoordinate in project nifi by apache.
the class StandardReportingTaskDAO method verifyUpdate.
private void verifyUpdate(final ReportingTaskNode reportingTask, final ReportingTaskDTO reportingTaskDTO) {
// ensure the state, if specified, is valid
if (isNotNull(reportingTaskDTO.getState())) {
try {
final ScheduledState purposedScheduledState = ScheduledState.valueOf(reportingTaskDTO.getState());
// only attempt an action if it is changing
if (!purposedScheduledState.equals(reportingTask.getScheduledState())) {
// perform the appropriate action
switch(purposedScheduledState) {
case RUNNING:
reportingTask.verifyCanStart();
break;
case STOPPED:
switch(reportingTask.getScheduledState()) {
case RUNNING:
reportingTask.verifyCanStop();
break;
case DISABLED:
reportingTask.verifyCanEnable();
break;
}
break;
case DISABLED:
reportingTask.verifyCanDisable();
break;
}
}
} catch (IllegalArgumentException iae) {
throw new IllegalArgumentException(String.format("The specified reporting task state (%s) is not valid. Valid options are 'RUNNING', 'STOPPED', and 'DISABLED'.", reportingTaskDTO.getState()));
}
}
boolean modificationRequest = false;
if (isAnyNotNull(reportingTaskDTO.getName(), reportingTaskDTO.getSchedulingStrategy(), reportingTaskDTO.getSchedulingPeriod(), reportingTaskDTO.getAnnotationData(), reportingTaskDTO.getProperties(), reportingTaskDTO.getBundle())) {
modificationRequest = true;
// validate the request
final List<String> requestValidation = validateProposedConfiguration(reportingTask, reportingTaskDTO);
// ensure there was no validation errors
if (!requestValidation.isEmpty()) {
throw new ValidationException(requestValidation);
}
}
final BundleDTO bundleDTO = reportingTaskDTO.getBundle();
if (bundleDTO != null) {
// ensures all nodes in a cluster have the bundle, throws exception if bundle not found for the given type
final BundleCoordinate bundleCoordinate = BundleUtils.getBundle(reportingTask.getCanonicalClassName(), bundleDTO);
// ensure we are only changing to a bundle with the same group and id, but different version
reportingTask.verifyCanUpdateBundle(bundleCoordinate);
}
if (modificationRequest) {
reportingTask.verifyCanUpdate();
}
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi by apache.
the class StandardReportingTaskDAO method updateBundle.
private void updateBundle(ReportingTaskNode reportingTask, ReportingTaskDTO reportingTaskDTO) {
final BundleDTO bundleDTO = reportingTaskDTO.getBundle();
if (bundleDTO != null) {
final BundleCoordinate incomingCoordinate = BundleUtils.getBundle(reportingTask.getCanonicalClassName(), bundleDTO);
final BundleCoordinate existingCoordinate = reportingTask.getBundleCoordinate();
if (!existingCoordinate.getCoordinate().equals(incomingCoordinate.getCoordinate())) {
try {
// we need to use the property descriptors from the temp component here in case we are changing from a ghost component to a real component
final ConfigurableComponent tempComponent = ExtensionManager.getTempComponent(reportingTask.getCanonicalClassName(), incomingCoordinate);
final Set<URL> additionalUrls = reportingTask.getAdditionalClasspathResources(tempComponent.getPropertyDescriptors());
reloadComponent.reload(reportingTask, reportingTask.getCanonicalClassName(), incomingCoordinate, additionalUrls);
} catch (ReportingTaskInstantiationException e) {
throw new NiFiCoreException(String.format("Unable to update reporting task %s from %s to %s due to: %s", reportingTaskDTO.getId(), reportingTask.getBundleCoordinate().getCoordinate(), incomingCoordinate.getCoordinate(), e.getMessage()), e);
}
}
}
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi-minifi by apache.
the class FlowEnricher method enrichComponent.
private void enrichComponent(EnrichingElementAdapter componentToEnrich, Map<String, Bundle> componentToEnrichVersionToBundles) throws FlowEnrichmentException {
if (componentToEnrich.getBundleElement() != null) {
return;
}
BundleCoordinate enrichingBundleCoordinate = null;
if (!componentToEnrichVersionToBundles.isEmpty()) {
// If there is only one supporting bundle, choose it, otherwise carry out additional analysis
if (componentToEnrichVersionToBundles.size() == 1) {
BundleDetails enrichingBundleDetails = componentToEnrichVersionToBundles.entrySet().iterator().next().getValue().getBundleDetails();
enrichingBundleCoordinate = enrichingBundleDetails.getCoordinate();
// Adjust the bundle to reflect the values we learned from the Extension Manager
componentToEnrich.setBundleInformation(enrichingBundleCoordinate);
componentToEnrich.setDependsUponBundleCoordinate(enrichingBundleDetails.getDependencyCoordinate());
} else {
// multiple options
final Set<String> componentToEnrichBundleVersions = componentToEnrichVersionToBundles.values().stream().map(bundle -> bundle.getBundleDetails().getCoordinate().getVersion()).collect(Collectors.toSet());
// Select the last version of those available for the enriching bundle
final String bundleVersion = componentToEnrichBundleVersions.stream().sorted().reduce((version, otherVersion) -> otherVersion).get();
final BundleCoordinate enrichingCoordinate = componentToEnrichVersionToBundles.get(bundleVersion).getBundleDetails().getCoordinate();
componentToEnrich.setBundleInformation(enrichingCoordinate);
logger.warn("Multiple enriching bundle options were available for component {}. The automatically selected enriching bundle was {}", new Object[] { componentToEnrich.getComponentClass(), enrichingCoordinate });
}
} else {
logger.warn("Could not find any eligible bundles for {}. Automatic start of the flow cannot be guaranteed.", componentToEnrich.getComponentClass());
}
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi-minifi by apache.
the class NarClassLoaders method load.
/**
* Should be called at most once.
*/
private InitContext load(final File frameworkWorkingDir, final File extensionsWorkingDir) throws IOException, ClassNotFoundException {
// get the system classloader
final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// get the current context class loader
ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
// find all nar files and create class loaders for them.
final Map<String, Bundle> narDirectoryBundleLookup = new LinkedHashMap<>();
final Map<String, ClassLoader> narCoordinateClassLoaderLookup = new HashMap<>();
final Map<String, Set<BundleCoordinate>> narIdBundleLookup = new HashMap<>();
// make sure the nar directory is there and accessible
FileUtils.ensureDirectoryExistAndCanReadAndWrite(frameworkWorkingDir);
FileUtils.ensureDirectoryExistAndCanReadAndWrite(extensionsWorkingDir);
final List<File> narWorkingDirContents = new ArrayList<>();
final File[] frameworkWorkingDirContents = frameworkWorkingDir.listFiles();
if (frameworkWorkingDirContents != null) {
narWorkingDirContents.addAll(Arrays.asList(frameworkWorkingDirContents));
}
final File[] extensionsWorkingDirContents = extensionsWorkingDir.listFiles();
if (extensionsWorkingDirContents != null) {
narWorkingDirContents.addAll(Arrays.asList(extensionsWorkingDirContents));
}
if (!narWorkingDirContents.isEmpty()) {
final List<BundleDetails> narDetails = new ArrayList<>();
final Map<String, String> narCoordinatesToWorkingDir = new HashMap<>();
// load the nar details which includes and nar dependencies
for (final File unpackedNar : narWorkingDirContents) {
BundleDetails narDetail = null;
try {
narDetail = getNarDetails(unpackedNar);
} catch (IllegalStateException e) {
logger.warn("Unable to load NAR {} due to {}, skipping...", new Object[] { unpackedNar.getAbsolutePath(), e.getMessage() });
}
// prevent the application from starting when there are two NARs with same group, id, and version
final String narCoordinate = narDetail.getCoordinate().getCoordinate();
if (narCoordinatesToWorkingDir.containsKey(narCoordinate)) {
final String existingNarWorkingDir = narCoordinatesToWorkingDir.get(narCoordinate);
throw new IllegalStateException("Unable to load NAR with coordinates " + narCoordinate + " and working directory " + narDetail.getWorkingDirectory() + " because another NAR with the same coordinates already exists at " + existingNarWorkingDir);
}
narDetails.add(narDetail);
narCoordinatesToWorkingDir.put(narCoordinate, narDetail.getWorkingDirectory().getCanonicalPath());
}
int narCount;
do {
// record the number of nars to be loaded
narCount = narDetails.size();
// attempt to create each nar class loader
for (final Iterator<BundleDetails> narDetailsIter = narDetails.iterator(); narDetailsIter.hasNext(); ) {
final BundleDetails narDetail = narDetailsIter.next();
final BundleCoordinate narDependencyCoordinate = narDetail.getDependencyCoordinate();
// see if this class loader is eligible for loading
ClassLoader narClassLoader = null;
if (narDependencyCoordinate == null) {
narClassLoader = createNarClassLoader(narDetail.getWorkingDirectory(), currentContextClassLoader);
} else {
final String dependencyCoordinateStr = narDependencyCoordinate.getCoordinate();
// if the declared dependency has already been loaded
if (narCoordinateClassLoaderLookup.containsKey(dependencyCoordinateStr)) {
final ClassLoader narDependencyClassLoader = narCoordinateClassLoaderLookup.get(dependencyCoordinateStr);
narClassLoader = createNarClassLoader(narDetail.getWorkingDirectory(), narDependencyClassLoader);
} else {
// get all bundles that match the declared dependency id
final Set<BundleCoordinate> coordinates = narIdBundleLookup.get(narDependencyCoordinate.getId());
// ensure there are known bundles that match the declared dependency id
if (coordinates != null && !coordinates.contains(narDependencyCoordinate)) {
// ensure the declared dependency only has one possible bundle
if (coordinates.size() == 1) {
// get the bundle with the matching id
final BundleCoordinate coordinate = coordinates.stream().findFirst().get();
// if that bundle is loaded, use it
if (narCoordinateClassLoaderLookup.containsKey(coordinate.getCoordinate())) {
logger.warn(String.format("While loading '%s' unable to locate exact NAR dependency '%s'. Only found one possible match '%s'. Continuing...", narDetail.getCoordinate().getCoordinate(), dependencyCoordinateStr, coordinate.getCoordinate()));
final ClassLoader narDependencyClassLoader = narCoordinateClassLoaderLookup.get(coordinate.getCoordinate());
narClassLoader = createNarClassLoader(narDetail.getWorkingDirectory(), narDependencyClassLoader);
}
}
}
}
}
// if we were able to create the nar class loader, store it and remove the details
final ClassLoader bundleClassLoader = narClassLoader;
if (bundleClassLoader != null) {
narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, bundleClassLoader));
narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), narClassLoader);
narDetailsIter.remove();
}
}
// attempt to load more if some were successfully loaded this iteration
} while (narCount != narDetails.size());
// see if any nars couldn't be loaded
for (final BundleDetails narDetail : narDetails) {
logger.warn(String.format("Unable to resolve required dependency '%s'. Skipping NAR '%s'", narDetail.getDependencyCoordinate().getId(), narDetail.getWorkingDirectory().getAbsolutePath()));
}
}
// find the framework bundle, NarUnpacker already checked that there was a framework NAR and that there was only one
final Bundle frameworkBundle = narDirectoryBundleLookup.values().stream().filter(b -> b.getBundleDetails().getCoordinate().getId().equals(FRAMEWORK_NAR_ID)).findFirst().orElse(null);
return new InitContext(frameworkWorkingDir, extensionsWorkingDir, frameworkBundle, new LinkedHashMap<>(narDirectoryBundleLookup));
}
use of org.apache.nifi.bundle.BundleCoordinate in project nifi-minifi by apache.
the class FlowEnricherTest method generateBundle.
private static Bundle generateBundle(String group, String id, String version, BundleCoordinate dependencyCoordinate) {
final File workingDirectory = new File("src/test/resources");
final BundleCoordinate bundleCoordinate = new BundleCoordinate(group, id, version);
final String buildTag = "HEAD";
final String buildRevision = "1";
final String buildBranch = "DEV";
final String buildTimestamp = "2017-01-01 00:00:00";
final String buildJdk = "JDK8";
final String builtBy = "somebody";
Builder bundleBuilder = new Builder().workingDir(workingDirectory).coordinate(bundleCoordinate).buildTag(buildTag).buildRevision(buildRevision).buildBranch(buildBranch).buildTimestamp(buildTimestamp).buildJdk(buildJdk).builtBy(builtBy);
if (dependencyCoordinate != null) {
bundleBuilder.dependencyCoordinate(dependencyCoordinate);
}
return new Bundle(bundleBuilder.build(), mockClassLoader);
}
Aggregations