diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java index 13ce80de07a1..b280a74e7086 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java @@ -56,6 +56,7 @@ import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue; import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; +import java.io.IOException; import java.util.*; public class MavenProjectsManagerWatcher { @@ -395,9 +396,9 @@ public class MavenProjectsManagerWatcher { filesToUpdate.removeAll(filesToRemove); scheduleUpdate(filesToUpdate, filesToRemove, false, forceImportAndResolve); } - } - clearLists(); + clearLists(); + } } private boolean areFileSetsInitialised() { @@ -426,6 +427,9 @@ public class MavenProjectsManagerWatcher { } private static abstract class MyFileChangeListenerBase implements BulkFileListener { + + private static final Key CONTENT_CRC_KEY = Key.create("MyFileChangeListenerBase"); + protected abstract boolean isRelevant(String path); protected abstract void updateFile(VirtualFile file); @@ -453,6 +457,21 @@ public class MavenProjectsManagerWatcher { deleteRecursively(moveEvent.getFile()); } } + else if (each instanceof VFileContentChangeEvent) { + VirtualFile virtualFile = each.getFile(); + if (virtualFile == null) continue; + + if (virtualFile.getLength() < 40 * 1024) { + try { + String content = VfsUtil.loadText(virtualFile); + int crc = MavenUtil.getXmlCrc(content); + virtualFile.putUserData(CONTENT_CRC_KEY, crc); + } + catch (IOException e) { + // Ignore + } + } + } } } } @@ -489,7 +508,25 @@ public class MavenProjectsManagerWatcher { } } else if (each instanceof VFileContentChangeEvent) { - updateFile(each.getFile()); + VirtualFile virtualFile = each.getFile(); + if (virtualFile == null) continue; + + Integer oldCrc = virtualFile.getUserData(CONTENT_CRC_KEY); + if (oldCrc != null) { + try { + virtualFile.putUserData(CONTENT_CRC_KEY, null); + + String content = VfsUtil.loadText(virtualFile); + int newCrc = MavenUtil.getXmlCrc(content); + + if (newCrc == oldCrc) continue; + } + catch (IOException e) { + // Ignore + } + } + + updateFile(virtualFile); } else if (each instanceof VFilePropertyChangeEvent) { if (isRenamed(each)) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index d05fc5fa4122..23577805661f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -19,6 +19,8 @@ import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; +import com.intellij.lexer.Lexer; +import com.intellij.lexer.XmlLexer; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; @@ -44,6 +46,8 @@ import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.xml.XmlTokenType; import com.intellij.util.Function; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; @@ -65,6 +69,7 @@ import java.util.concurrent.Future; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import java.util.zip.CRC32; public class MavenUtil { public static final String MAVEN_NOTIFICATION_GROUP = "Maven"; @@ -630,4 +635,41 @@ public class MavenUtil { public interface MavenTaskHandler { void waitFor(); } + + public static int getXmlCrc(@NotNull String xmlText) { + Lexer lexer = new XmlLexer(); + lexer.start(xmlText.trim()); + + CRC32 crc = new CRC32(); + + while (true) { + IElementType tokenType = lexer.getTokenType(); + if (tokenType == null) break; + + if (XmlTokenType.XML_REAL_WHITE_SPACE == tokenType + || XmlTokenType.XML_WHITE_SPACE == tokenType + || XmlTokenType.COMMENTS.contains(tokenType)) { + crc.update(1); + + do { + lexer.advance(); + tokenType = lexer.getTokenType(); + } + while (XmlTokenType.XML_REAL_WHITE_SPACE == tokenType + || XmlTokenType.XML_WHITE_SPACE == tokenType + || XmlTokenType.COMMENTS.contains(tokenType)); + } + else { + for (int start = lexer.getTokenStart(), end = lexer.getTokenEnd(); start < end; start++) { + char a = xmlText.charAt(start); + crc.update(a); + crc.update(a >>> 8); + } + + lexer.advance(); + } + } + + return (int)crc.getValue(); + } }