public @Override void execute() throws BuildException {
    String p = getProject().getProperty("javahelpbin.exclude.modules");
    excludedModulesSet = parseExcludeModulesProperty(p);
    for (FileSet fs : filesets) {
      FileScanner scanner = fs.getDirectoryScanner(getProject());
      File dir = scanner.getBasedir();
      String[] files = scanner.getIncludedFiles();

      URLClassLoader globalClassLoader;
      Map<String, URLClassLoader> classLoaderMap;
      try {
        globalClassLoader = createGlobalClassLoader(dir, files);
        classLoaderMap = createClassLoaderMap(dir, files);
        NbDocsStreamHandler.NbDocsURLConnection.globalClassLoader.set(globalClassLoader);
        NbDocsStreamHandler.NbDocsURLConnection.classLoaderMap.set(classLoaderMap);
        CheckLinks.handlerFactory.set(new NbDocsStreamHandler.Factory());
        for (Map.Entry<String, URLClassLoader> entry : classLoaderMap.entrySet()) {
          String cnb = entry.getKey();
          if (excludedModulesSet.contains(cnb)) {
            log("skipping module: " + cnb, Project.MSG_INFO);
            continue;
          }
          URLClassLoader l = entry.getValue();
          Manifest m;
          InputStream is = l.getResourceAsStream("META-INF/MANIFEST.MF");
          if (is != null) {
            try {
              m = new Manifest(is);
            } finally {
              is.close();
            }
          } else {
            log("No manifest in " + Arrays.toString(l.getURLs()), Project.MSG_WARN);
            continue;
          }
          for (String resource :
              new String[] {
                m.getMainAttributes().getValue("OpenIDE-Module-Layer"),
                "META-INF/generated-layer.xml"
              }) {
            if (resource == null) {
              continue;
            }
            URL layer = l.getResource(resource);
            if (layer == null) {
              log("No layer " + resource, Project.MSG_VERBOSE);
              continue;
            }
            Document doc;
            try {
              doc = XMLUtil.parse(new InputSource(layer.toString()), false, false, null, NO_DTDS);
            } catch (SAXException x) {
              log("Could not parse " + layer, x, Project.MSG_WARN);
              continue;
            }
            for (Element services : XMLUtil.findSubElements(doc.getDocumentElement())) {
              if (!services.getTagName().equals("folder")
                  || !services.getAttribute("name").equals("Services")) {
                continue;
              }
              for (Element javahelp : XMLUtil.findSubElements(services)) {
                if (!javahelp.getTagName().equals("folder")
                    || !javahelp.getAttribute("name").equals("JavaHelp")) {
                  continue;
                }
                JAVAHELP:
                for (Element registration : XMLUtil.findSubElements(javahelp)) {
                  if (!registration.getTagName().equals("file")) {
                    continue;
                  }
                  InputSource input = null;
                  String url = registration.getAttribute("url");
                  if (!url.isEmpty()) {
                    input = new InputSource(new URL(layer, url).toString());
                  } else {
                    NodeList nl = registration.getChildNodes();
                    for (int i = 0; i < nl.getLength(); i++) {
                      if (nl.item(i).getNodeType() == Node.CDATA_SECTION_NODE) {
                        if (input == null) {
                          input = new InputSource(new StringReader(nl.item(i).getNodeValue()));
                        } else {
                          log(
                              "Multiple content for "
                                  + registration.getAttribute("name")
                                  + " in "
                                  + layer,
                              Project.MSG_WARN);
                          continue JAVAHELP;
                        }
                      }
                    }
                    if (input == null) {
                      log(
                          "No content for " + registration.getAttribute("name") + " in " + layer,
                          Project.MSG_WARN);
                    }
                  }
                  Document doc2;
                  try {
                    doc2 = XMLUtil.parse(input, false, false, null, NO_DTDS);
                  } catch (SAXException x) {
                    log(
                        "Could not parse " + registration.getAttribute("name") + " in " + layer,
                        x,
                        Project.MSG_WARN);
                    continue;
                  }
                  URI helpsetref = URI.create(doc2.getDocumentElement().getAttribute("url"));
                  if ("nbdocs".equals(helpsetref.getScheme())
                      && helpsetref.getAuthority() == null) {
                    try {
                      helpsetref =
                          new URI(
                              helpsetref.getScheme(),
                              cnb,
                              helpsetref.getPath(),
                              helpsetref.getQuery(),
                              helpsetref.getFragment());
                    } catch (URISyntaxException x) {
                      throw new BuildException(x);
                    }
                  }
                  log("checking: " + helpsetref, Project.MSG_INFO);
                  checkHelpSetURL(
                      CheckLinks.toURL(helpsetref), globalClassLoader, l, classLoaderMap, cnb);
                }
              }
            }
          }
        }
      } catch (IOException x) {
        throw new BuildException(x);
      } finally {
        NbDocsStreamHandler.NbDocsURLConnection.globalClassLoader.set(null);
        NbDocsStreamHandler.NbDocsURLConnection.classLoaderMap.set(null);
        CheckLinks.handlerFactory.set(null);
      }
    }
  }