code: protected void slowScan() {
          synchronized (slowScanLock) {
              if (haveSlowResults) {
                  return;
              }
              if (slowScanning) {
                  while (slowScanning) {
                      try {
                          slowScanLock.wait();
                      } catch (InterruptedException e) {
                          // Empty
                      }
                  }
                  return;
              }
              slowScanning = true;
          }
          try {
              synchronized (this) {
  
                  // set in/excludes to reasonable defaults if needed:
                  boolean nullIncludes = (includes == null);
                  includes = nullIncludes ? new String[] {"**"} : includes;
                  boolean nullExcludes = (excludes == null);
                  excludes = nullExcludes ? new String[0] : excludes;
  
                  String[] excl = new String[dirsExcluded.size()];
                  dirsExcluded.copyInto(excl);
  
                  String[] notIncl = new String[dirsNotIncluded.size()];
                  dirsNotIncluded.copyInto(notIncl);
  
                  processSlowScan(excl);
                  processSlowScan(notIncl);
                  clearCaches();
                  includes = nullIncludes ? null : includes;
                  excludes = nullExcludes ? null : excludes;
              }
          } finally {
              synchronized (slowScanLock) {
                  haveSlowResults = true;
                  slowScanning = false;
                  slowScanLock.notifyAll();
              }
          }
      }
docs: Top level invocation for a slow scan. A slow scan builds up a full
  list of excluded/included files/directories, whereas a fast scan
  will only have full results for included files, as it ignores
  directories which can't possibly hold any included files/directories.
  <p>
  Returns immediately if a slow scan has already been completed.