| /*=============================================================================# |
| # Copyright (c) 2018, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.rhelp.server.update; |
| |
| import static org.eclipse.statet.rhelp.server.Application.BUNDLE_ID; |
| |
| import java.io.IOException; |
| import java.nio.file.ClosedWatchServiceException; |
| import java.nio.file.FileSystems; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.StandardWatchEventKinds; |
| import java.nio.file.WatchEvent; |
| import java.nio.file.WatchKey; |
| import java.nio.file.WatchService; |
| import java.util.List; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.statet.jcommons.runtime.CommonsRuntime; |
| import org.eclipse.statet.jcommons.status.ErrorStatus; |
| import org.eclipse.statet.jcommons.status.InfoStatus; |
| |
| import org.eclipse.statet.rj.renv.core.RLibLocation; |
| import org.eclipse.statet.rj.renv.core.RLibPaths; |
| |
| |
| public class RLibPathsMonitor implements Runnable { |
| |
| |
| private final REnvIndexer indexer; |
| |
| private WatchService watchService; |
| |
| |
| public RLibPathsMonitor(final REnvIndexer indexer) { |
| this.indexer= indexer; |
| } |
| |
| |
| public void check(final RLibPaths rLibPaths) { |
| try { |
| ensureService(); |
| |
| for (final RLibLocation location : rLibPaths.getRLibLocations()) { |
| final Path path= location.getDirectoryPath(); |
| if (path != null && Files.isDirectory(path)) { |
| path.register(this.watchService, |
| StandardWatchEventKinds.ENTRY_CREATE, |
| StandardWatchEventKinds.ENTRY_DELETE, |
| StandardWatchEventKinds.OVERFLOW ); |
| } |
| } |
| |
| } |
| catch (final IOException e) { |
| CommonsRuntime.log(new ErrorStatus(BUNDLE_ID, |
| String.format("%1$sAn error occurred when setting up R lib paths monitor.", |
| this.indexer.getLogPrefix() ), |
| e )); |
| } |
| } |
| |
| public void stop() { |
| try { |
| stopService(); |
| } |
| catch (final IOException e) { |
| CommonsRuntime.log(new ErrorStatus(BUNDLE_ID, |
| String.format("%1$sAn error occurred when stopping R lib paths monitor.", |
| this.indexer.getLogPrefix() ), |
| e )); |
| } |
| } |
| |
| private synchronized void ensureService() throws IOException { |
| if (this.watchService == null) { |
| this.watchService= FileSystems.getDefault().newWatchService(); |
| |
| this.indexer.getController().startMonitor(this); |
| } |
| } |
| |
| private synchronized void stopService() throws IOException { |
| if (this.watchService != null) { |
| this.watchService.close(); |
| } |
| } |
| |
| |
| private boolean isTempFolder(final String fileName) { |
| if (fileName.length() >= 5) { |
| if (fileName.startsWith("_test_") || fileName.startsWith("_TEST_")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| return true; |
| } |
| if (fileName.startsWith("file") || fileName.startsWith("FILE")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| final char c= fileName.charAt(4); |
| return (c >= '0' && c <= '9'); |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public void run() { |
| try { |
| CommonsRuntime.log(new InfoStatus(BUNDLE_ID, |
| String.format("%1$sR lib paths monitor started.", |
| this.indexer.getLogPrefix() ))); |
| |
| boolean update= false; |
| while (true) { |
| try { |
| final WatchKey key= (update) ? |
| this.watchService.poll(1000, TimeUnit.MILLISECONDS) : |
| this.watchService.take(); |
| if (key == null) { |
| assert(update); |
| update= false; |
| this.indexer.schedule(REnvIndexer.LIB_PATHS_MONITOR); |
| continue; |
| } |
| else { |
| final List<WatchEvent<?>> events= key.pollEvents(); |
| for (final WatchEvent<?> event : events) { |
| if (event.kind() == StandardWatchEventKinds.OVERFLOW) { |
| update= true; |
| break; |
| } |
| final Path path= (Path) event.context(); |
| if (path != null && !isTempFolder(path.getFileName().toString())) { |
| update= true; |
| break; |
| } |
| } |
| key.reset(); |
| } |
| } |
| catch (final InterruptedException e) { |
| } |
| catch (final ClosedWatchServiceException e) { |
| synchronized (this) { |
| this.watchService= null; |
| } |
| return; |
| } |
| } |
| } |
| catch (final Throwable e) { |
| CommonsRuntime.log(new ErrorStatus(BUNDLE_ID, |
| String.format("%1$sR lib paths monitor did not complete normally.", |
| this.indexer.getLogPrefix() ), |
| e )); |
| } |
| } |
| |
| } |