<commit_before>/*******************************************************************************
 * Copyright (c) 2012-2017 Red Hat, Inc.
 * 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:
 *   Red Hat, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.api.project.server;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.model.project.NewProjectConfig;
import org.eclipse.che.api.core.model.project.ProjectConfig;
import org.eclipse.che.api.core.model.project.SourceStorage;
import org.eclipse.che.api.core.model.project.type.ProjectType;
import org.eclipse.che.api.core.util.LineConsumerFactory;
import org.eclipse.che.api.project.server.RegisteredProject.Problem;
import org.eclipse.che.api.project.server.handlers.CreateProjectHandler;
import org.eclipse.che.api.project.server.handlers.ProjectHandlerRegistry;
import org.eclipse.che.api.project.server.importer.ProjectImporter;
import org.eclipse.che.api.project.server.importer.ProjectImporterRegistry;
import org.eclipse.che.api.project.server.type.AttributeValue;
import org.eclipse.che.api.project.server.type.BaseProjectType;
import org.eclipse.che.api.project.server.type.ProjectTypeDef;
import org.eclipse.che.api.project.server.type.ProjectTypeRegistry;
import org.eclipse.che.api.project.server.type.ProjectTypeResolution;
import org.eclipse.che.api.project.shared.dto.event.FileWatcherEventType;
import org.eclipse.che.api.vfs.Path;
import org.eclipse.che.api.vfs.VirtualFile;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.VirtualFileSystemProvider;
import org.eclipse.che.api.vfs.impl.file.FileTreeWatcher;
import org.eclipse.che.api.vfs.impl.file.FileWatcherNotificationHandler;
import org.eclipse.che.api.vfs.impl.file.FileWatcherNotificationListener;
import org.eclipse.che.api.vfs.search.Searcher;
import org.eclipse.che.api.vfs.search.SearcherProvider;
import org.eclipse.che.api.vfs.watcher.FileWatcherManager;
import org.eclipse.che.commons.lang.concurrent.LoggingUncaughtExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static org.eclipse.che.api.core.ErrorCodes.NOT_UPDATED_PROJECT;

/**
 * Facade for all project related operations.
 *
 * @author gazarenkov
 */
@Singleton
public class ProjectManager {
    private static final Logger LOG = LoggerFactory.getLogger(ProjectManager.class);

    private final VirtualFileSystem              vfs;
    private final ProjectTypeRegistry            projectTypeRegistry;
    private final ProjectRegistry                projectRegistry;
    private final ProjectHandlerRegistry         handlers;
    private final ProjectImporterRegistry        importers;
    private final FileTreeWatcher                fileWatcher;
    private final FileWatcherNotificationHandler fileWatchNotifier;
    private final ExecutorService                executor;
    private final WorkspaceProjectsSyncer        workspaceProjectsHolder;
    private final FileWatcherManager             fileWatcherManager;

    @Inject
    public ProjectManager(VirtualFileSystemProvider vfsProvider,
                          ProjectTypeRegistry projectTypeRegistry,
                          ProjectRegistry projectRegistry,
                          ProjectHandlerRegistry handlers,
                          ProjectImporterRegistry importers,
                          FileWatcherNotificationHandler fileWatcherNotificationHandler,
                          FileTreeWatcher fileTreeWatcher,
                          WorkspaceProjectsSyncer workspaceProjectsHolder,
                          FileWatcherManager fileWatcherManager) throws ServerException {
        this.vfs = vfsProvider.getVirtualFileSystem();
        this.projectTypeRegistry = projectTypeRegistry;
        this.projectRegistry = projectRegistry;
        this.handlers = handlers;
        this.importers = importers;
        this.fileWatchNotifier = fileWatcherNotificationHandler;
        this.fileWatcher = fileTreeWatcher;
        this.workspaceProjectsHolder = workspaceProjectsHolder;
        this.fileWatcherManager = fileWatcherManager;

        executor = Executors.newFixedThreadPool(1 + Runtime.getRuntime().availableProcessors(),
                                                new ThreadFactoryBuilder().setNameFormat("ProjectService-IndexingThread-")
                                                                          .setUncaughtExceptionHandler(
                                                                                  LoggingUncaughtExceptionHandler.getInstance())
                                                                          .setDaemon(true).build());
    }

    void initWatcher() throws IOException {
        FileWatcherNotificationListener defaultListener =
                new FileWatcherNotificationListener(file -> !(file.getPath().toString().contains(".che")
                                                              || file.getPath().toString().contains(".#"))) {
                    @Override
                    public void onFileWatcherEvent(VirtualFile virtualFile, FileWatcherEventType eventType) {
                        LOG.debug("FS event detected: " + eventType + " " + virtualFile.getPath().toString() + " " + virtualFile.isFile());
                    }
                };
        fileWatchNotifier.addNotificationListener(defaultListener);
        try {
            fileWatcher.startup();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
            fileWatchNotifier.removeNotificationListener(defaultListener);
        }
    }

    @PreDestroy
    void stop() {
        executor.shutdownNow();
    }

    public FolderEntry getProjectsRoot() throws ServerException {
        return new FolderEntry(vfs.getRoot(), projectRegistry);
    }

    public Searcher getSearcher() throws NotFoundException, ServerException {<commit_msg>Fixed bug when the project still present after deletion through terminal or project service (#6013)<commit_after>/*******************************************************************************
 * Copyright (c) 2012-2017 Red Hat, Inc.
 * 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:
 *   Red Hat, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.api.project.server;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.model.project.NewProjectConfig;
import org.eclipse.che.api.core.model.project.ProjectConfig;
import org.eclipse.che.api.core.model.project.SourceStorage;
import org.eclipse.che.api.core.model.project.type.ProjectType;
import org.eclipse.che.api.core.util.LineConsumerFactory;
import org.eclipse.che.api.project.server.RegisteredProject.Problem;
import org.eclipse.che.api.project.server.handlers.CreateProjectHandler;
import org.eclipse.che.api.project.server.handlers.ProjectHandlerRegistry;
import org.eclipse.che.api.project.server.importer.ProjectImporter;
import org.eclipse.che.api.project.server.importer.ProjectImporterRegistry;
import org.eclipse.che.api.project.server.type.AttributeValue;
import org.eclipse.che.api.project.server.type.BaseProjectType;
import org.eclipse.che.api.project.server.type.ProjectTypeDef;
import org.eclipse.che.api.project.server.type.ProjectTypeRegistry;
import org.eclipse.che.api.project.server.type.ProjectTypeResolution;
import org.eclipse.che.api.project.shared.dto.event.FileWatcherEventType;
import org.eclipse.che.api.vfs.Path;
import org.eclipse.che.api.vfs.VirtualFile;
import org.eclipse.che.api.vfs.VirtualFileSystem;
import org.eclipse.che.api.vfs.VirtualFileSystemProvider;
import org.eclipse.che.api.vfs.impl.file.FileTreeWatcher;
import org.eclipse.che.api.vfs.impl.file.FileWatcherNotificationHandler;
import org.eclipse.che.api.vfs.impl.file.FileWatcherNotificationListener;
import org.eclipse.che.api.vfs.search.Searcher;
import org.eclipse.che.api.vfs.search.SearcherProvider;
import org.eclipse.che.api.vfs.watcher.FileWatcherManager;
import org.eclipse.che.commons.lang.concurrent.LoggingUncaughtExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static org.eclipse.che.api.core.ErrorCodes.NOT_UPDATED_PROJECT;
import static org.eclipse.che.api.vfs.watcher.FileWatcherManager.EMPTY_CONSUMER;

/**
 * Facade for all project related operations.
 *
 * @author gazarenkov
 */
@Singleton
public class ProjectManager {
    private static final Logger LOG = LoggerFactory.getLogger(ProjectManager.class);

    private final VirtualFileSystem              vfs;
    private final ProjectTypeRegistry            projectTypeRegistry;
    private final ProjectRegistry                projectRegistry;
    private final ProjectHandlerRegistry         handlers;
    private final ProjectImporterRegistry        importers;
    private final FileTreeWatcher                fileWatcher;
    private final FileWatcherNotificationHandler fileWatchNotifier;
    private final ExecutorService                executor;
    private final WorkspaceProjectsSyncer        workspaceProjectsHolder;
    private final FileWatcherManager             fileWatcherManager;

    private int rootProjcetOperationSetId;

    @Inject
    public ProjectManager(VirtualFileSystemProvider vfsProvider,
                          ProjectTypeRegistry projectTypeRegistry,
                          ProjectRegistry projectRegistry,
                          ProjectHandlerRegistry handlers,
                          ProjectImporterRegistry importers,
                          FileWatcherNotificationHandler fileWatcherNotificationHandler,
                          FileTreeWatcher fileTreeWatcher,
                          WorkspaceProjectsSyncer workspaceProjectsHolder,
                          FileWatcherManager fileWatcherManager) throws ServerException {
        this.vfs = vfsProvider.getVirtualFileSystem();
        this.projectTypeRegistry = projectTypeRegistry;
        this.projectRegistry = projectRegistry;
        this.handlers = handlers;
        this.importers = importers;
        this.fileWatchNotifier = fileWatcherNotificationHandler;
        this.fileWatcher = fileTreeWatcher;
        this.workspaceProjectsHolder = workspaceProjectsHolder;
        this.fileWatcherManager = fileWatcherManager;

        executor = Executors.newFixedThreadPool(1 + Runtime.getRuntime().availableProcessors(),
                                                new ThreadFactoryBuilder().setNameFormat("ProjectService-IndexingThread-")
                                                                          .setUncaughtExceptionHandler(
                                                                                  LoggingUncaughtExceptionHandler.getInstance())
                                                                          .setDaemon(true).build());
    }

    @PostConstruct
    private void postConstruct() {
        String rootPath = vfs.getRoot().getPath().toString();
        rootProjcetOperationSetId = fileWatcherManager.registerByPath(rootPath, EMPTY_CONSUMER, EMPTY_CONSUMER, projectPath -> {
            try {
                projectRegistry.removeProjects(projectPath);
                workspaceProjectsHolder.sync(projectRegistry);
            } catch (ServerException e) {
                LOG.error("Could not remove or synchronize  project: {}", projectPath);
            }
        });
    }

    @PreDestroy
    private void preDestroy() {
        fileWatcherManager.unRegisterByPath(rootProjcetOperationSetId);
    }

    void initWatcher() throws IOException {
        FileWatcherNotificationListener defaultListener =
                new FileWatcherNotificationListener(file -> !(file.getPath().toString().contains(".che")
                                                              || file.getPath().toString().contains(".#"))) {
                    @Override
                    public void onFileWatcherEvent(VirtualFile virtualFile, FileWatcherEventType eventType) {
                        LOG.debug("FS event detected: " + eventType + " " + virtualFile.getPath().toString() + " " + virtualFile.isFile());
                    }
                };
        fileWatchNotifier.addNotificationListener(defaultListener);
        try {
            fileWatcher.startup();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
            fileWatchNotifier.removeNotificationListener(defaultListener);
        }
    }

    @PreDestroy
    void stop() {
        executor.shutdownNow();
    }

    public FolderEntry getProjectsRoot() throws ServerException {
        return new FolderEntry(vfs.getRoot(), projectRegistry);
    }

    public Searcher getSearcher() throws NotFoundException, ServerException {
{'fraction_non_alphanumeric': 0.10378813275226283, 'fraction_numerical': 0.002279584311096212, 'mean_word_length': 3.0064464141821112, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1379054', 'n_tokens_mistral': 3759, 'n_tokens_neox': 3682, 'n_words': 670}