Search in sources :

Example 6 with BundleDetails

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();
    }
}
Also used : BundleDetails(org.apache.nifi.bundle.BundleDetails) Attributes(java.util.jar.Attributes) Manifest(java.util.jar.Manifest) File(java.io.File) BundleCoordinate(org.apache.nifi.bundle.BundleCoordinate) FileInputStream(java.io.FileInputStream)

Example 7 with BundleDetails

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));
}
Also used : Bundle(org.apache.nifi.bundle.Bundle) Arrays(java.util.Arrays) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) BundleCoordinate(org.apache.nifi.bundle.BundleCoordinate) LoggerFactory(org.slf4j.LoggerFactory) Set(java.util.Set) IOException(java.io.IOException) HashMap(java.util.HashMap) BundleDetails(org.apache.nifi.bundle.BundleDetails) File(java.io.File) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) List(java.util.List) FileUtils(org.apache.nifi.util.FileUtils) Map(java.util.Map) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) BundleCoordinate(org.apache.nifi.bundle.BundleCoordinate) LinkedHashMap(java.util.LinkedHashMap) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Bundle(org.apache.nifi.bundle.Bundle) BundleDetails(org.apache.nifi.bundle.BundleDetails) File(java.io.File)

Example 8 with BundleDetails

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());
}
Also used : BundleDetails(org.apache.nifi.bundle.BundleDetails) File(java.io.File) Test(org.junit.Test)

Example 9 with BundleDetails

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());
}
Also used : BundleDetails(org.apache.nifi.bundle.BundleDetails) File(java.io.File) Test(org.junit.Test)

Example 10 with BundleDetails

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;
}
Also used : JVMSystemDiagnosticsSnapshotDTO(org.apache.nifi.web.api.dto.diagnostics.JVMSystemDiagnosticsSnapshotDTO) BundleDetails(org.apache.nifi.bundle.BundleDetails) Bundle(org.apache.nifi.bundle.Bundle)

Aggregations

BundleDetails (org.apache.nifi.bundle.BundleDetails)13 File (java.io.File)10 Bundle (org.apache.nifi.bundle.Bundle)8 BundleCoordinate (org.apache.nifi.bundle.BundleCoordinate)5 HashMap (java.util.HashMap)4 Set (java.util.Set)3 Test (org.junit.Test)3 FileInputStream (java.io.FileInputStream)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 LinkedHashMap (java.util.LinkedHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 List (java.util.List)2 Map (java.util.Map)2 Attributes (java.util.jar.Attributes)2 Manifest (java.util.jar.Manifest)2 NiFiProperties (org.apache.nifi.util.NiFiProperties)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2