use of org.apache.nifi.bundle.BundleDetails in project nifi by apache.
the class FlowResource method getAboutInfo.
/**
* Retrieves details about this NiFi to put in the About dialog.
*
* @return An aboutEntity.
*/
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("about")
@ApiOperation(value = "Retrieves details about this NiFi to put in the About dialog", response = AboutEntity.class, authorizations = { @Authorization(value = "Read - /flow") })
@ApiResponses(value = { @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), @ApiResponse(code = 401, message = "Client could not be authenticated."), @ApiResponse(code = 403, message = "Client is not authorized to make this request."), @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") })
public Response getAboutInfo() {
authorizeFlow();
// create the about dto
final AboutDTO aboutDTO = new AboutDTO();
aboutDTO.setTitle("NiFi");
aboutDTO.setUri(generateResourceUri());
aboutDTO.setTimezone(new Date());
// get the content viewer url
final NiFiProperties properties = getProperties();
aboutDTO.setContentViewerUrl(properties.getProperty(NiFiProperties.CONTENT_VIEWER_URL));
final Bundle frameworkBundle = NarClassLoaders.getInstance().getFrameworkBundle();
if (frameworkBundle != null) {
final BundleDetails frameworkDetails = frameworkBundle.getBundleDetails();
// set the version
aboutDTO.setVersion(frameworkDetails.getCoordinate().getVersion());
// Get build info
aboutDTO.setBuildTag(frameworkDetails.getBuildTag());
aboutDTO.setBuildRevision(frameworkDetails.getBuildRevision());
aboutDTO.setBuildBranch(frameworkDetails.getBuildBranch());
aboutDTO.setBuildTimestamp(frameworkDetails.getBuildTimestampDate());
}
// create the response entity
final AboutEntity entity = new AboutEntity();
entity.setAbout(aboutDTO);
// generate the response
return generateOkResponse(entity).build();
}
use of org.apache.nifi.bundle.BundleDetails 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.BundleDetails 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));
}
Aggregations