use of org.apache.nifi.bundle.BundleDetails in project nifi by apache.
the class NarBundleUtil method fromNarDirectory.
/**
* Creates a BundleDetails from the given NAR working directory.
*
* @param narDirectory the directory of an exploded NAR which contains a META-INF/MANIFEST.MF
*
* @return the BundleDetails constructed from the information in META-INF/MANIFEST.MF
*/
public static BundleDetails fromNarDirectory(final File narDirectory) throws IOException, IllegalStateException {
if (narDirectory == null) {
throw new IllegalArgumentException("NAR Directory cannot be null");
}
final File manifestFile = new File(narDirectory, "META-INF/MANIFEST.MF");
try (final FileInputStream fis = new FileInputStream(manifestFile)) {
final Manifest manifest = new Manifest(fis);
final Attributes attributes = manifest.getMainAttributes();
final BundleDetails.Builder builder = new BundleDetails.Builder();
builder.workingDir(narDirectory);
final String group = attributes.getValue(NarManifestEntry.NAR_GROUP.getManifestName());
final String id = attributes.getValue(NarManifestEntry.NAR_ID.getManifestName());
final String version = attributes.getValue(NarManifestEntry.NAR_VERSION.getManifestName());
builder.coordinate(new BundleCoordinate(group, id, version));
final String dependencyGroup = attributes.getValue(NarManifestEntry.NAR_DEPENDENCY_GROUP.getManifestName());
final String dependencyId = attributes.getValue(NarManifestEntry.NAR_DEPENDENCY_ID.getManifestName());
final String dependencyVersion = attributes.getValue(NarManifestEntry.NAR_DEPENDENCY_VERSION.getManifestName());
if (!StringUtils.isBlank(dependencyId)) {
builder.dependencyCoordinate(new BundleCoordinate(dependencyGroup, dependencyId, dependencyVersion));
}
builder.buildBranch(attributes.getValue(NarManifestEntry.BUILD_BRANCH.getManifestName()));
builder.buildTag(attributes.getValue(NarManifestEntry.BUILD_TAG.getManifestName()));
builder.buildRevision(attributes.getValue(NarManifestEntry.BUILD_REVISION.getManifestName()));
builder.buildTimestamp(attributes.getValue(NarManifestEntry.BUILD_TIMESTAMP.getManifestName()));
builder.buildJdk(attributes.getValue(NarManifestEntry.BUILD_JDK.getManifestName()));
builder.builtBy(attributes.getValue(NarManifestEntry.BUILT_BY.getManifestName()));
return builder.build();
}
}
use of org.apache.nifi.bundle.BundleDetails in project nifi by apache.
the class NarClassLoaders method load.
/**
* Should be called at most once.
*/
private InitContext load(final ClassLoader rootClassloader, final File frameworkWorkingDir, final File extensionsWorkingDir) throws IOException, ClassNotFoundException {
// 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());
}
// attempt to locate the jetty nar
ClassLoader jettyClassLoader = null;
for (final Iterator<BundleDetails> narDetailsIter = narDetails.iterator(); narDetailsIter.hasNext(); ) {
final BundleDetails narDetail = narDetailsIter.next();
// look for the jetty nar
if (JETTY_NAR_ID.equals(narDetail.getCoordinate().getId())) {
// create the jetty classloader
jettyClassLoader = createNarClassLoader(narDetail.getWorkingDirectory(), rootClassloader);
// remove the jetty nar since its already loaded
narDirectoryBundleLookup.put(narDetail.getWorkingDirectory().getCanonicalPath(), new Bundle(narDetail, jettyClassLoader));
narCoordinateClassLoaderLookup.put(narDetail.getCoordinate().getCoordinate(), jettyClassLoader);
narDetailsIter.remove();
}
// populate bundle lookup
narIdBundleLookup.computeIfAbsent(narDetail.getCoordinate().getId(), id -> new HashSet<>()).add(narDetail.getCoordinate());
}
// ensure the jetty nar was found
if (jettyClassLoader == null) {
throw new IllegalStateException("Unable to locate Jetty bundle.");
}
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(), jettyClassLoader);
} 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.BundleDetails in project nifi by apache.
the class NarBundleUtilTest method testManifestWithoutNarDependency.
@Test
public void testManifestWithoutNarDependency() throws IOException {
final File narDir = new File("src/test/resources/nars/nar-without-dependency");
final BundleDetails narDetails = NarBundleUtil.fromNarDirectory(narDir);
assertEquals(narDir.getPath(), narDetails.getWorkingDirectory().getPath());
assertEquals("org.apache.nifi", narDetails.getCoordinate().getGroup());
assertEquals("nifi-hadoop-nar", narDetails.getCoordinate().getId());
assertEquals("1.2.0", narDetails.getCoordinate().getVersion());
assertNull(narDetails.getDependencyCoordinate());
assertEquals("NIFI-3380", narDetails.getBuildBranch());
assertEquals("1.8.0_74", narDetails.getBuildJdk());
assertEquals("a032175", narDetails.getBuildRevision());
assertEquals("HEAD", narDetails.getBuildTag());
assertEquals("2017-01-23T10:36:27Z", narDetails.getBuildTimestamp());
assertEquals("bbende", narDetails.getBuiltBy());
}
use of org.apache.nifi.bundle.BundleDetails in project nifi by apache.
the class NarBundleUtilTest method testManifestWithoutVersioningAndBuildInfo.
@Test
public void testManifestWithoutVersioningAndBuildInfo() throws IOException {
final File narDir = new File("src/test/resources/nars/nar-without-versioning");
final BundleDetails narDetails = NarBundleUtil.fromNarDirectory(narDir);
assertEquals(narDir.getPath(), narDetails.getWorkingDirectory().getPath());
assertEquals(BundleCoordinate.DEFAULT_GROUP, narDetails.getCoordinate().getGroup());
assertEquals("nifi-hadoop-nar", narDetails.getCoordinate().getId());
assertEquals(BundleCoordinate.DEFAULT_VERSION, narDetails.getCoordinate().getVersion());
assertEquals(BundleCoordinate.DEFAULT_GROUP, narDetails.getDependencyCoordinate().getGroup());
assertEquals("nifi-hadoop-libraries-nar", narDetails.getDependencyCoordinate().getId());
assertEquals(BundleCoordinate.DEFAULT_VERSION, narDetails.getDependencyCoordinate().getVersion());
assertNull(narDetails.getBuildBranch());
assertEquals("1.8.0_74", narDetails.getBuildJdk());
assertNull(narDetails.getBuildRevision());
assertNull(narDetails.getBuildTag());
assertNull(narDetails.getBuildTimestamp());
assertEquals("bbende", narDetails.getBuiltBy());
}
use of org.apache.nifi.bundle.BundleDetails in project nifi by apache.
the class DtoFactory method createVersionInfoDTO.
public SystemDiagnosticsSnapshotDTO.VersionInfoDTO createVersionInfoDTO() {
final SystemDiagnosticsSnapshotDTO.VersionInfoDTO dto = new SystemDiagnosticsSnapshotDTO.VersionInfoDTO();
dto.setJavaVendor(System.getProperty("java.vendor"));
dto.setJavaVersion(System.getProperty("java.version"));
dto.setOsName(System.getProperty("os.name"));
dto.setOsVersion(System.getProperty("os.version"));
dto.setOsArchitecture(System.getProperty("os.arch"));
final Bundle frameworkBundle = NarClassLoaders.getInstance().getFrameworkBundle();
if (frameworkBundle != null) {
final BundleDetails frameworkDetails = frameworkBundle.getBundleDetails();
dto.setNiFiVersion(frameworkDetails.getCoordinate().getVersion());
// Get build info
dto.setBuildTag(frameworkDetails.getBuildTag());
dto.setBuildRevision(frameworkDetails.getBuildRevision());
dto.setBuildBranch(frameworkDetails.getBuildBranch());
dto.setBuildTimestamp(frameworkDetails.getBuildTimestampDate());
}
return dto;
}
Aggregations