tds/src/main/java/thredds/core/ConfigCatalogInitialization.java
private void checkCatalogToRead(ReadMode readMode, String catalogRelPath, boolean isRoot, long lastRead) throws IOException {
    if (exceedLimit) return;

    catalogRelPath = StringUtils.cleanPath(catalogRelPath);
    File catalogFile = new File(this.contentRootPath, catalogRelPath);
    if (!catalogFile.exists()) {
      catalogTracker.removeCatalog(catalogRelPath);
      logCatalogInit.error(ERROR + "initCatalog(): Catalog [" + catalogRelPath + "] does not exist.");
      return;
    }
    long lastModified = catalogFile.lastModified();
    if (!isRoot && readMode != ReadMode.always && lastModified < lastRead) return; // skip catalogs that havent changed
    if (!isRoot && readMode == ReadMode.triggerOnly) return;                    // skip non-root catalogs for trigger only
    if (show) System.out.printf("initCatalog %s%n", catalogRelPath);

    // make sure we havent already read it
    if (catPathMap.contains(catalogRelPath)) {
      logCatalogInit.error(ERROR + "initCatalog(): Catalog [" + catalogRelPath + "] already seen, possible loop (skip).");
      return;
    }
    catPathMap.add(catalogRelPath);
    Set<String> idSet = new HashSet<>();  // look for unique ids

    // if (logCatalogInit.isDebugEnabled()) logCatalogInit.debug("initCatalog {} -> {}", path, f.getAbsolutePath());

    // read it
    ConfigCatalog cat = readCatalog(catalogRelPath, catalogFile.getPath());
    if (cat == null) {
      logCatalogInit.error(ERROR + "initCatalog(): failed to read catalog <" + catalogFile.getPath() + ">.");
      return;
    }
    long catId = catalogTracker.put(new CatalogExt(0, catalogRelPath, isRoot, readNow));

    if (isRoot) {
      if (ccc != null) ccc.put(catalogRelPath, cat);
      allowedServices.addGlobalServices(cat.getServices());
      if (readMode == ReadMode.triggerOnly) return;                    // thats all we need
    }

    if (callback != null) callback.hasCatalogRef(cat);

    // look for datasetRoots
    for (DatasetRootConfig p : cat.getDatasetRoots())
      dataRootPathMatcher.addRoot(p, catalogRelPath, readMode == ReadMode.always); // check for duplicates on complete reread

    if (callback == null) {   // LOOK WTF?
      List<String> disallowedServices = allowedServices.getDisallowedServices(cat.getServices());
      if (!disallowedServices.isEmpty()) {
        allowedServices.getDisallowedServices(cat.getServices());
        logCatalogInit.error(ERROR + "initCatalog(): declared services: " + Arrays.toString(disallowedServices.toArray()) + " in catalog: " + catalogFile.getPath() + " are disallowed in threddsConfig file");
      }
    }

    // look for dataRoots in datasetScans and featureCollections
    dataRootPathMatcher.extractDataRoots(catalogRelPath, cat.getDatasetsLocal(), readMode == ReadMode.always, fcNameMap);

    // get the directory path, reletive to the rootDir
    int pos = catalogRelPath.lastIndexOf("/");
    String dirPath = (pos > 0) ? catalogRelPath.substring(0, pos + 1) : "";
    processDatasets(catId, readMode, dirPath, cat.getDatasetsLocal(), idSet);     // recurse

    // look for catalogScans
    for (CatalogScan catScan : cat.getCatalogScans()) {
      if (exceedLimit) return;
      Path relLocation = Paths.get(dirPath, catScan.getLocation());
      Path absLocation = Paths.get(catalogFile.getParent(), catScan.getLocation());
      // if (catalogWatcher != null) catalogWatcher.registerAll(absLocation);
      readCatsInDirectory(readMode, relLocation.toString(), absLocation);
    }
  }
private void checkCatalogToRead(ReadMode readMode, String catalogRelPath, boolean isRoot, long lastRead) throws IOException {
    if (exceedLimit) return;

    catalogRelPath = StringUtils.cleanPath(catalogRelPath);
    File catalogFile = new File(this.contentRootPath, catalogRelPath);
    if (!catalogFile.exists()) {
      catalogTracker.removeCatalog(catalogRelPath);
      logCatalogInit.error(ERROR + "initCatalog(): Catalog [" + catalogRelPath + "] does not exist.");
      return;
    }
    long lastModified = catalogFile.lastModified();
    if (!isRoot && readMode != ReadMode.always && lastModified < lastRead) return; // skip catalogs that havent changed
    if (!isRoot && readMode == ReadMode.triggerOnly) return;                    // skip non-root catalogs for trigger only
    if (show) System.out.printf("initCatalog %s%n", catalogRelPath);

    // make sure we havent already read it
    if (catPathMap.contains(catalogRelPath)) {
      logCatalogInit.error(ERROR + "initCatalog(): Catalog [" + catalogRelPath + "] already seen, possible loop (skip).");
      return;
    }
    catPathMap.add(catalogRelPath);
    Set<String> idSet = new HashSet<>();  // look for unique ids

    // if (logCatalogInit.isDebugEnabled()) logCatalogInit.debug("initCatalog {} -> {}", path, f.getAbsolutePath());

    // read it
    ConfigCatalog cat = readCatalog(catalogRelPath, catalogFile.getPath());
    if (cat == null) {
      logCatalogInit.error(ERROR + "initCatalog(): failed to read catalog <" + catalogFile.getPath() + ">.");
      return;
    }
    long catId = catalogTracker.put(new CatalogExt(0, catalogRelPath, isRoot, readNow));

    if (isRoot) {
      if (ccc != null) ccc.put(catalogRelPath, cat);
      allowedServices.addGlobalServices(cat.getServices());
      if (readMode == ReadMode.triggerOnly) return;                    // thats all we need
    }

    if (callback != null) callback.hasCatalogRef(cat);

    // look for datasetRoots
    for (DatasetRootConfig p : cat.getDatasetRoots())
      dataRootPathMatcher.addRoot(p, catalogRelPath, readMode == ReadMode.always); // check for duplicates on complete reread

    if (callback == null) {   // LOOK WTF?
      List<String> disallowedServices = allowedServices.getDisallowedServices(cat.getServices());
      if (!disallowedServices.isEmpty()) {
        allowedServices.getDisallowedServices(cat.getServices());
        logCatalogInit.error(ERROR + "initCatalog(): declared services: " + Arrays.toString(disallowedServices.toArray()) + " in catalog: " + catalogFile.getPath() + " are disallowed in threddsConfig file");
      }
    }

    // look for dataRoots in datasetScans and featureCollections
    dataRootPathMatcher.extractDataRoots(catalogRelPath, cat.getDatasetsLocal(), readMode == ReadMode.always, fcNameMap);

    // get the directory path, reletive to the rootDir
    int pos = catalogRelPath.lastIndexOf("/");
    String dirPath = (pos > 0) ? catalogRelPath.substring(0, pos + 1) : "";
    processDatasets(catId, readMode, dirPath, cat.getDatasetsLocal(), idSet);     // recurse

    // look for catalogScans
    for (CatalogScan catScan : cat.getCatalogScans()) {
      if (exceedLimit) return;
      Path relLocation = Paths.get(dirPath, catScan.getLocation());
      Path absLocation = Paths.get(catalogFile.getParent(), catScan.getLocation());
      // if (catalogWatcher != null) catalogWatcher.registerAll(absLocation);
      readCatsInDirectory(readMode, relLocation.toString(), absLocation);
    }
  }
catalogRelpath must be relative to rootDir