All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.swoval.files.SymlinkFollowingPathWatcher Maven / Gradle / Ivy

There is a newer version: 2.1.12
Show newest version
package com.swoval.files;

import static com.swoval.functional.Filters.AllPass;

import com.swoval.files.FileTreeViews.Observer;
import com.swoval.files.PathWatchers.Event;
import com.swoval.files.PathWatchers.Event.Kind;
import com.swoval.functional.Either;
import com.swoval.functional.Filter;
import com.swoval.runtime.Platform;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Iterator;

class SymlinkFollowingPathWatcher implements PathWatcher {
  private final SymlinkWatcher symlinkWatcher;
  private final PathWatcher pathWatcher;
  private final Observers observers = new Observers<>();
  private final DirectoryRegistry pathWatcherDirectoryRegistry;

  SymlinkFollowingPathWatcher(
      final PathWatcher pathWatcher, final DirectoryRegistry directoryRegistry)
      throws InterruptedException, IOException {
    this.pathWatcher = pathWatcher;
    this.pathWatcherDirectoryRegistry = directoryRegistry;
    this.symlinkWatcher =
        new SymlinkWatcher(
            Platform.isMac()
                ? new ApplePathWatcher(new DirectoryRegistryImpl())
                : PlatformWatcher.make(false, new DirectoryRegistryImpl()));
    pathWatcher.addObserver(
        new Observer() {
          @Override
          public void onError(final Throwable t) {
            observers.onError(t);
          }

          @Override
          public void onNext(final Event event) {
            final TypedPath typedPath = event.getTypedPath();
            if (typedPath.exists() && typedPath.isSymbolicLink()) {
              try {
                final int maxDepth = directoryRegistry.maxDepthFor(typedPath.getPath());
                symlinkWatcher.addSymlink(typedPath.getPath(), maxDepth);
                if (typedPath.isDirectory()) {
                  handleNewDirectory(typedPath.getPath(), maxDepth, true);
                }
              } catch (final IOException e) {
                observers.onError(e);
              }
            } else if (!typedPath.exists()) {
              symlinkWatcher.remove(typedPath.getPath());
            }
            observers.onNext(event);
          }
        });
    symlinkWatcher.addObserver(
        new Observer() {
          @Override
          public void onError(final Throwable t) {
            observers.onError(t);
          }

          @Override
          public void onNext(final Event event) {
            observers.onNext(event);
          }
        });
  }

  private void handleNewDirectory(final Path path, final int maxDepth, final boolean trigger)
      throws IOException {
    final Iterator it = FileTreeViews.list(path, maxDepth, AllPass).iterator();
    while (it.hasNext()) {
      final TypedPath tp = it.next();
      if (tp.isSymbolicLink()) {
        final Path p = tp.getPath();
        symlinkWatcher.addSymlink(p, pathWatcherDirectoryRegistry.maxDepthFor(p));
      }
      if (trigger) {
        observers.onNext(new Event(tp, Kind.Create));
      }
    }
  }

  @Override
  public Either register(final Path path, final int maxDepth) {
    final Path absolutePath = path.isAbsolute() ? path : path.toAbsolutePath();
    final Either pathWatcherResult =
        pathWatcher.register(absolutePath, maxDepth);
    Either listResult = pathWatcherResult;
    if (pathWatcherResult.isRight()) {
      try {
        handleNewDirectory(absolutePath, maxDepth, false);
        listResult = Either.right(true);
      } catch (final IOException e) {
        listResult = Either.left(e);
      }
    }
    return listResult;
  }

  @SuppressWarnings("EmptyCatchBlock")
  @Override
  public void unregister(final Path path) {
    final Path absolutePath = path.isAbsolute() ? path : path.toAbsolutePath();
    try {
      final Iterator it =
          FileTreeViews.list(
                  absolutePath,
                  pathWatcherDirectoryRegistry.maxDepthFor(absolutePath),
                  new Filter() {
                    @Override
                    public boolean accept(final TypedPath typedPath) {
                      return typedPath.isSymbolicLink();
                    }
                  })
              .iterator();
      while (it.hasNext()) {
        symlinkWatcher.remove(it.next().getPath());
      }
    } catch (final IOException e) {
    }
    pathWatcher.unregister(absolutePath);
  }

  @Override
  public void close() {
    pathWatcher.close();
    symlinkWatcher.close();
  }

  @Override
  public int addObserver(final Observer observer) {
    return observers.addObserver(observer);
  }

  @Override
  public void removeObserver(int handle) {
    observers.removeObserver(handle);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy