/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.openapi.file.exclude;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Map;

/**
 * Retrieves plain text file type from open projects' configurations.
 *
 * @author Rustam Vishnyakov
 */
public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener {
  private final Map<Project, Collection<VirtualFile>> myPlainTextFileSets = new ConcurrentWeakHashMap<Project, Collection<VirtualFile>>();
  private volatile boolean mySetsInitialized = false;
  private static final Object LOCK = new Object();

  public EnforcedPlainTextFileTypeManager() {
    ProjectManager.getInstance().addProjectManagerListener(this);
  }

  public boolean isMarkedAsPlainText(VirtualFile file) {
    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
    if (!mySetsInitialized) {
      synchronized (LOCK) {
        if (!mySetsInitialized) {
          initPlainTextFileSets();
          mySetsInitialized = true;
        }
      }
    }
    for (Project project : myPlainTextFileSets.keySet()) {
      Collection<VirtualFile> projectSet = myPlainTextFileSets.get(project);
      if (projectSet != null && projectSet.contains(file)) return true;
    }
    return false;
  }

  private void initPlainTextFileSets() {
    Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
    for (Project openProject : openProjects) {
      addProjectPlainTextFiles(openProject);
    }
  }

  public static boolean isApplicableFor(@NotNull VirtualFile file) {
    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
    FileType originalType = FileTypeManager.getInstance().getFileTypeByFileName(file.getName());
    return !originalType.isBinary() && originalType != FileTypes.PLAIN_TEXT && originalType != StdFileTypes.JAVA;
  }

  public void markAsPlainText(@NotNull Project project, VirtualFile... files) {
    setPlainTextStatus(project, true, files);
  }

  public void resetOriginalFileType(@NotNull Project project, VirtualFile... files) {
    setPlainTextStatus(project, false, files);
  }

  private void setPlainTextStatus(@NotNull final Project project, final boolean isAdded, final VirtualFile... files) {
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(new Runnable() {
          @Override
          public void run() {
            ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager = ProjectPlainTextFileTypeManager.getInstance(project);
            for (VirtualFile file : files) {
              if (projectPlainTextFileTypeManager.hasProjectContaining(file)) {
                ensureProjectFileSetAdded(project, projectPlainTextFileTypeManager);
                if (isAdded ?
                    projectPlainTextFileTypeManager.addFile(file) :
                    projectPlainTextFileTypeManager.removeFile(file)) {
                  FileBasedIndex.getInstance().requestReindex(file);
                }
              }
            }
          }
        }, false, true);
      }
    });
  }

  private void ensureProjectFileSetAdded(@NotNull Project project,
                                         @NotNull ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager) {
    if (!myPlainTextFileSets.containsKey(project)) {
      myPlainTextFileSets.put(project, projectPlainTextFileTypeManager.getFiles());
    }
  }

  private static class EnforcedPlainTextFileTypeManagerHolder {
    private static final EnforcedPlainTextFileTypeManager ourInstance = ServiceManager.getService(EnforcedPlainTextFileTypeManager.class);
  }

  public static EnforcedPlainTextFileTypeManager getInstance() {
    return EnforcedPlainTextFileTypeManagerHolder.ourInstance;
  }

  @Override
  public void projectOpened(Project project) {
    addProjectPlainTextFiles(project);
  }

  @Override
  public boolean canCloseProject(Project project) {
    return true;
  }

  @Override
  public void projectClosed(Project project) {
    myPlainTextFileSets.remove(project);
  }

  @Override
  public void projectClosing(Project project) {
  }

  private void addProjectPlainTextFiles(@NotNull Project project) {
    if (!project.isDisposed()) {
      ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager = ProjectPlainTextFileTypeManager.getInstance(project);
      if (projectPlainTextFileTypeManager != null) {
        myPlainTextFileSets.put(project, projectPlainTextFileTypeManager.getFiles());
      }
    }
  }
}

@@ -1118,67 +1118,8 @@
 er;%0A
-import com.intellij.openapi.roots.ex.ProjectRootManagerEx;%0A
 impo
@@ -1210,16 +1210,62 @@
 WithId;%0A
+import com.intellij.util.FileContentUtilCore;%0A
 import c
@@ -3671,147 +3671,8 @@
 ) %7B%0A
-        ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(new Runnable() %7B%0A          @Override%0A          public void run() %7B%0A    
     
@@ -3803,20 +3803,16 @@
         
-    
 for (Vir
@@ -3842,28 +3842,24 @@
 %7B%0A          
-   
- 
 if (projectP
@@ -3904,36 +3904,32 @@
 aining(file)) %7B%0A
-    
             ensu
@@ -4001,28 +4001,24 @@
             
-   
- 
 if (isAdded 
@@ -4019,20 +4019,16 @@
 Added ?%0A
-    
         
@@ -4091,36 +4091,32 @@
                 
-  
-  
 projectPlainText
@@ -4143,36 +4143,32 @@
 veFile(file)) %7B%0A
-    
               Fi
@@ -4224,34 +4224,26 @@
             
-    %7D%0A    
+%7D%0A
           %7D%0A
@@ -4242,36 +4242,32 @@
       %7D%0A        
-    
 %7D%0A          %7D%0A  
@@ -4264,34 +4264,46 @@
     
-  %7D%0A        %7D, false, true
+FileContentUtilCore.reparseFiles(files
 );%0A 

Use FileContentUtilCore.reparseFiles() instead of makeRootsChange, [CR-CR-IC-4656] comment