/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.vfs.search.impl;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.commons.lang.concurrent.LoggingUncaughtExceptionHandler;
import org.eclipse.che.api.vfs.VirtualFileFilter;
import org.eclipse.che.api.vfs.VirtualFileFilters;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.search.MediaTypeFilter;
import org.eclipse.che.api.vfs.search.Searcher;
import org.eclipse.che.api.vfs.search.SearcherProvider;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.collect.Lists.newArrayList;
public abstract class AbstractLuceneSearcherProvider implements SearcherProvider {
protected final VirtualFileFilter excludeFileIndexFilters;
protected final AtomicReference<Searcher> searcherReference = new AtomicReference<>();
private final ExecutorService executor;
/**
* @param excludeFileIndexFilters
* set filter for files that should not be indexed
*/
protected AbstractLuceneSearcherProvider(Set<VirtualFileFilter> excludeFileIndexFilters) {
this.excludeFileIndexFilters = mergeFileIndexFilters(excludeFileIndexFilters);
executor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
.setDaemon(true)
.setUncaughtExceptionHandler(
LoggingUncaughtExceptionHandler.getInstance())
.setNameFormat("LuceneSearcherInitThread")
.build());
}
private VirtualFileFilter mergeFileIndexFilters(Set<VirtualFileFilter> fileIndexFilters) {
final VirtualFileFilter filter;
if (fileIndexFilters.isEmpty()) {
filter = new MediaTypeFilter();
} else {
final List<VirtualFileFilter> myFilters = newArrayList(new MediaTypeFilter());
myFilters.addAll(fileIndexFilters);
filter = VirtualFileFilters.createOrFilter(myFilters);
}
return filter;
}
@Override
public Searcher getSearcher(VirtualFileSystem virtualFileSystem, boolean create) throws ServerException {
Searcher cachedSearcher = searcherReference.get();
if (cachedSearcher == null && create) {
LuceneSearcher searcher = createLuceneSearcher(() -> searcherReference.set(null));
if (searcherReference.compareAndSet(null, searcher)) {
searcher.initAsynchronously(executor, virtualFileSystem);
}
cachedSearcher = searcherReference.get();
}
return cachedSearcher;
}
@PreDestroy
void stop() {
executor.shutdownNow();
}
@Override
public Searcher getSearcher(VirtualFileSystem virtualFileSystem) throws ServerException {
return getSearcher(virtualFileSystem, true);
}
protected abstract LuceneSearcher createLuceneSearcher(CloseCallback closeCallback);
@Override
public void close() throws ServerException {
Searcher searcher = searcherReference.get();
if (searcher != null) {
searcher.close();
}
searcherReference.set(null);
}
public interface CloseCallback {
void onClose();
}
}