blob: 5ec74b8c0ce362e0dab8aad82210240537c7eb66 [file] [log] [blame]
/*=============================================================================#
# 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 ));
}
}
}