private synchronized void updateDelegateClassloader()

in modules/vfs-class-loader/src/main/java/org/apache/accumulo/classloader/vfs/AccumuloVFSClassLoader.java [349:442]


  private synchronized void updateDelegateClassloader() throws Exception {
    try {
      // Re-resolve the files on the classpath, things may have changed.
      long retries = 0;
      long currentSleepMillis = sleepInterval;
      printDebug("Looking for files on classpath: " + this.getClassPath());
      FileObject[] classpathFiles = VFSManager.resolve(this.getClassPath());
      if (classpathFiles.length == 0) {
        while (classpathFiles.length == 0 && retryPermitted(retries)) {
          try {
            printWarn("VFS path was empty.  Waiting " + currentSleepMillis + " ms to retry");
            Thread.sleep(currentSleepMillis);
            classpathFiles = VFSManager.resolve(this.getClassPath());
            retries++;
            currentSleepMillis = Math.min(maxWaitInterval, currentSleepMillis + sleepInterval);
          } catch (InterruptedException e) {
            printError("VFS Retry Interruped");
            e.printStackTrace();
            throw new RuntimeException(e);
          }
        }
      }
      if (classpathFiles.length == 0) {
        printError("AccumuloVFSClassLoader has no resources on classpath");
      }
      this.files = classpathFiles;
      // Remove old files from monitor
      VFSClassLoaderWrapper currentDelegate = this.cl;
      if (null != currentDelegate) {
        forEachCatchRTEs(Arrays.stream(currentDelegate.getFileObjects()), f -> {
          removeFile(f);
          printDebug("removed from monitor: " + f.toString());
        });
      }
      // There is a chance that the listener was removed from the top level directory or
      // its children if they were deleted within some time window. Re-add files to be
      // monitored. The Monitor will ignore files that are already/still being monitored.
      // forEachCatchRTEs will capture a stream of thrown exceptions.
      // and can collect them to list or reduce into one exception
      forEachCatchRTEs(Arrays.stream(this.files), f -> {
        addFileToMonitor(f);
        printDebug("now monitoring: " + f.toString());
      });
      // Create the new classloader delegate
      if (DEBUG) {
        printDebug("Rebuilding dynamic classloader using files: "
            + Arrays.stream(this.files).map(Object::toString).collect(Collectors.joining(",")));
      }
      VFSClassLoaderWrapper newDelegate;
      var parent = getParent();
      if (!this.isPostDelegationModel()) {
        // This is the normal classloader parent delegation model
        printDebug("Creating new pre-delegating VFSClassLoaderWrapper");
        newDelegate = new VFSClassLoaderWrapper(this.files, VFSManager.get(), parent);
      } else {
        // This delegates to the parent after we lookup locally first.
        printDebug("Creating new post-delegating VFSClassLoaderWrapper");
        newDelegate = new VFSClassLoaderWrapper(this.files, VFSManager.get(), parent) {
          @Override
          public synchronized Class<?> loadClass(String name, boolean resolve)
              throws ClassNotFoundException {
            // Check to see if this ClassLoader has already loaded the class
            Class<?> c = this.findLoadedClass(name);
            if (c != null) {
              if (DEBUG) {
                printDebug("Returning already loaded class: " + name + "@" + c.hashCode()
                    + " from classloader: " + c.getClassLoader().hashCode());
              }
              return c;
            }
            try {
              // try finding this class here instead of parent
              Class<?> clazz = super.findClass(name);
              if (DEBUG) {
                printDebug("Returning newly loaded class: " + name + "@" + clazz.hashCode()
                    + " from classloader: " + clazz.getClassLoader().hashCode());
              }
              return clazz;
            } catch (ClassNotFoundException e) {
              printDebug("Class " + name + " not found in classloader: " + this.hashCode()
                  + ", delegating to parent.");
            }
            printDebug("Loading class " + name + " from parent classloader");
            return super.loadClass(name, resolve);
          }
        };
      }
      updateLock.writeLock().lock();
      this.cl = newDelegate;
      printDebug("AccumuloVFSClassLoader set, hash=" + this.cl.hashCode());
    } finally {
      updateLock.writeLock().unlock();
    }
  }