tds/src/main/java/thredds/core/ConfigCatalogInitialization.java
private void processDatasets(long catId, ReadMode readMode, String dirPath, List<Dataset> datasets, Set<String> idMap) throws IOException {
    if (exceedLimit) return;

    for (Dataset ds : datasets) {
      if (datasetTracker.trackDataset(catId, ds, callback)) countDatasets++;
      if (maxDatasetsProcess > 0 && countDatasets > maxDatasetsProcess) exceedLimit = true;

      // look for duplicate ids
      String id = ds.getID();
      if (id != null) {
        if (idMap.contains(id)) {
          logCatalogInit.error(ERROR + "Duplicate id on  '" + ds.getName() + "' id= '" + id + "'");
        } else {
          idMap.add(id);
        }
      }

      if ((ds instanceof DatasetScan) || (ds instanceof FeatureCollectionRef)) continue;
      if (ds instanceof CatalogScan) continue;

      if (ds instanceof CatalogRef) { // follow catalog refs
        CatalogRef catref = (CatalogRef) ds;
        String href = catref.getXlinkHref();
        // if (logCatalogInit.isDebugEnabled()) logCatalogInit.debug("  catref.getXlinkHref=" + href);

        // Check that catRef is relative
        if (!href.startsWith("http:")) {
          // Clean up relative URLs that start with "./"
          if (href.startsWith("./")) {
            href = href.substring(2);
          }

          String path;
          String contextPathPlus = this.contextPath + "/";
          if (href.startsWith(contextPathPlus)) {
            path = href.substring(contextPathPlus.length()); // absolute starting from content root
          } else if (href.startsWith("/")) {
            // Drop the catRef because it points to a non-TDS served catalog.
            logCatalogInit.error(ERROR + "Skipping catalogRef <xlink:href=" + href + ">. Reference is relative to the server outside the context path [" + contextPathPlus + "]. " +
                    "Parent catalog info: Name=\"" + catref.getParentCatalog().getName() + "\"; Base URI=\"" + catref.getParentCatalog().getUriString() + "\"; dirPath=\"" + dirPath + "\".");
            continue;
          } else {
            path = dirPath + href;  // reletive starting from current directory
          }

          CatalogExt ext = catalogTracker.get(path);
          long lastRead = (ext == null) ? 0 : ext.getLastRead();
          checkCatalogToRead(readMode, path, false, lastRead);
        }

      } else {
        // recurse through nested datasets
        processDatasets(catId, readMode, dirPath, ds.getDatasetsLocal(), idMap);
      }
    }
  }
private void processDatasets(long catId, ReadMode readMode, String dirPath, List<Dataset> datasets, Set<String> idMap) throws IOException {
    if (exceedLimit) return;

    for (Dataset ds : datasets) {
      if (datasetTracker.trackDataset(catId, ds, callback)) countDatasets++;
      if (maxDatasetsProcess > 0 && countDatasets > maxDatasetsProcess) exceedLimit = true;

      // look for duplicate ids
      String id = ds.getID();
      if (id != null) {
        if (idMap.contains(id)) {
          logCatalogInit.error(ERROR + "Duplicate id on  '" + ds.getName() + "' id= '" + id + "'");
        } else {
          idMap.add(id);
        }
      }

      if ((ds instanceof DatasetScan) || (ds instanceof FeatureCollectionRef)) continue;
      if (ds instanceof CatalogScan) continue;

      if (ds instanceof CatalogRef) { // follow catalog refs
        CatalogRef catref = (CatalogRef) ds;
        String href = catref.getXlinkHref();
        // if (logCatalogInit.isDebugEnabled()) logCatalogInit.debug("  catref.getXlinkHref=" + href);

        // Check that catRef is relative
        if (!href.startsWith("http:")) {
          // Clean up relative URLs that start with "./"
          if (href.startsWith("./")) {
            href = href.substring(2);
          }

          String path;
          String contextPathPlus = this.contextPath + "/";
          if (href.startsWith(contextPathPlus)) {
            path = href.substring(contextPathPlus.length()); // absolute starting from content root
          } else if (href.startsWith("/")) {
            // Drop the catRef because it points to a non-TDS served catalog.
            logCatalogInit.error(ERROR + "Skipping catalogRef <xlink:href=" + href + ">. Reference is relative to the server outside the context path [" + contextPathPlus + "]. " +
                    "Parent catalog info: Name=\"" + catref.getParentCatalog().getName() + "\"; Base URI=\"" + catref.getParentCatalog().getUriString() + "\"; dirPath=\"" + dirPath + "\".");
            continue;
          } else {
            path = dirPath + href;  // reletive starting from current directory
          }

          CatalogExt ext = catalogTracker.get(path);
          long lastRead = (ext == null) ? 0 : ext.getLastRead();
          checkCatalogToRead(readMode, path, false, lastRead);
        }

      } else {
        // recurse through nested datasets
        processDatasets(catId, readMode, dirPath, ds.getDatasetsLocal(), idMap);
      }
    }
  }
dirPath = the directory path, reletive to the rootDir