Ejemplo n.º 1
0
  /**
   * Loads the details for the specified NAR. The details will be extracted from the manifest file.
   *
   * @param narDirectory the nar directory
   * @return details about the NAR
   * @throws IOException ioe
   */
  private static NarDetails getNarDetails(final File narDirectory) throws IOException {
    final NarDetails narDetails = new NarDetails();
    narDetails.setNarWorkingDirectory(narDirectory);

    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();

      // get the nar details
      narDetails.setNarId(attributes.getValue("Nar-Id"));
      narDetails.setNarDependencyId(attributes.getValue("Nar-Dependency-Id"));
    }

    return narDetails;
  }
Ejemplo n.º 2
0
  /** 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();

    // find all nar files and create class loaders for them.
    final Map<String, ClassLoader> extensionDirectoryClassLoaderLookup = new LinkedHashMap<>();
    final Map<String, ClassLoader> narIdClassLoaderLookup = new HashMap<>();

    // make sure the nar directory is there and accessible
    FileUtils.ensureDirectoryExistAndCanAccess(frameworkWorkingDir);
    FileUtils.ensureDirectoryExistAndCanAccess(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<NarDetails> narDetails = new ArrayList<>();

      // load the nar details which includes and nar dependencies
      for (final File unpackedNar : narWorkingDirContents) {
        final NarDetails narDetail = getNarDetails(unpackedNar);

        // ensure the nar contained an identifier
        if (narDetail.getNarId() == null) {
          logger.warn("No NAR Id found. Skipping: " + unpackedNar.getAbsolutePath());
          continue;
        }

        // store the nar details
        narDetails.add(narDetail);
      }

      // attempt to locate the jetty nar
      ClassLoader jettyClassLoader = null;
      for (final Iterator<NarDetails> narDetailsIter = narDetails.iterator();
          narDetailsIter.hasNext(); ) {
        final NarDetails narDetail = narDetailsIter.next();

        // look for the jetty nar
        if (JETTY_NAR_ID.equals(narDetail.getNarId())) {
          // create the jetty classloader
          jettyClassLoader =
              createNarClassLoader(narDetail.getNarWorkingDirectory(), systemClassLoader);

          // remove the jetty nar since its already loaded
          narIdClassLoaderLookup.put(narDetail.getNarId(), jettyClassLoader);
          narDetailsIter.remove();
          break;
        }
      }

      // 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<NarDetails> narDetailsIter = narDetails.iterator();
            narDetailsIter.hasNext(); ) {
          final NarDetails narDetail = narDetailsIter.next();
          final String narDependencies = narDetail.getNarDependencyId();

          // see if this class loader is eligible for loading
          ClassLoader narClassLoader = null;
          if (narDependencies == null) {
            narClassLoader =
                createNarClassLoader(narDetail.getNarWorkingDirectory(), jettyClassLoader);
          } else if (narIdClassLoaderLookup.containsKey(narDetail.getNarDependencyId())) {
            narClassLoader =
                createNarClassLoader(
                    narDetail.getNarWorkingDirectory(),
                    narIdClassLoaderLookup.get(narDetail.getNarDependencyId()));
          }

          // if we were able to create the nar class loader, store it and remove the details
          if (narClassLoader != null) {
            extensionDirectoryClassLoaderLookup.put(
                narDetail.getNarWorkingDirectory().getCanonicalPath(), narClassLoader);
            narIdClassLoaderLookup.put(narDetail.getNarId(), 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 NarDetails narDetail : narDetails) {
        logger.warn(
            String.format(
                "Unable to resolve required dependency '%s'. Skipping NAR %s",
                narDetail.getNarDependencyId(),
                narDetail.getNarWorkingDirectory().getAbsolutePath()));
      }
    }

    return new InitContext(
        frameworkWorkingDir,
        extensionsWorkingDir,
        narIdClassLoaderLookup.get(FRAMEWORK_NAR_ID),
        new LinkedHashMap<>(extensionDirectoryClassLoaderLookup));
  }