1 11 package org.eclipse.jdt.internal.core.index; 12 13 import java.io.*; 14 15 import org.eclipse.jdt.core.compiler.CharOperation; 16 import org.eclipse.jdt.core.search.*; 17 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; 18 import org.eclipse.jdt.internal.compiler.util.SimpleSet; 19 import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor; 20 21 28 29 public class Index { 30 31 public String containerPath; 32 public ReadWriteMonitor monitor; 33 34 protected DiskIndex diskIndex; 35 protected MemoryIndex memoryIndex; 36 37 40 static final int MATCH_RULE_INDEX_MASK = 41 SearchPattern.R_EXACT_MATCH | 42 SearchPattern.R_PREFIX_MATCH | 43 SearchPattern.R_PATTERN_MATCH | 44 SearchPattern.R_REGEXP_MATCH | 45 SearchPattern.R_CASE_SENSITIVE | 46 SearchPattern.R_CAMELCASE_MATCH; 47 48 public static boolean isMatch(char[] pattern, char[] word, int matchRule) { 49 if (pattern == null) return true; 50 int patternLength = pattern.length; 51 int wordLength = word.length; 52 if (patternLength == 0) return matchRule != SearchPattern.R_EXACT_MATCH; 53 if (wordLength == 0) return (matchRule & SearchPattern.R_PATTERN_MATCH) != 0 && patternLength == 1 && pattern[0] == '*'; 54 55 boolean isCamelCase = (matchRule & SearchPattern.R_CAMELCASE_MATCH) != 0; 57 if (isCamelCase && pattern[0] == word[0] && CharOperation.camelCaseMatch(pattern, word)) { 58 return true; 59 } 60 61 matchRule &= ~SearchPattern.R_CAMELCASE_MATCH; 63 switch(matchRule & MATCH_RULE_INDEX_MASK) { 64 case SearchPattern.R_EXACT_MATCH : 65 if (!isCamelCase) { 66 return patternLength == wordLength && CharOperation.equals(pattern, word, false); 67 } 68 case SearchPattern.R_PREFIX_MATCH : 70 return patternLength <= wordLength && CharOperation.prefixEquals(pattern, word, false); 71 case SearchPattern.R_PATTERN_MATCH : 72 return CharOperation.match(pattern, word, false); 73 case SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE : 74 if (!isCamelCase) { 75 return pattern[0] == word[0] && patternLength == wordLength && CharOperation.equals(pattern, word); 76 } 77 case SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE : 79 return pattern[0] == word[0] && patternLength <= wordLength && CharOperation.prefixEquals(pattern, word); 80 case SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE : 81 return CharOperation.match(pattern, word, true); 82 } 83 return false; 84 } 85 86 87 public Index(String fileName, String containerPath, boolean reuseExistingFile) throws IOException { 88 this.containerPath = containerPath; 89 this.monitor = new ReadWriteMonitor(); 90 91 this.memoryIndex = new MemoryIndex(); 92 this.diskIndex = new DiskIndex(fileName); 93 this.diskIndex.initialize(reuseExistingFile); 94 } 95 public void addIndexEntry(char[] category, char[] key, String containerRelativePath) { 96 this.memoryIndex.addIndexEntry(category, key, containerRelativePath); 97 } 98 public String containerRelativePath(String documentPath) { 99 int index = documentPath.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR); 100 if (index == -1) { 101 index = this.containerPath.length(); 102 if (documentPath.length() <= index) 103 throw new IllegalArgumentException ("Document path " + documentPath + " must be relative to " + this.containerPath); } 105 return documentPath.substring(index + 1); 106 } 107 public File getIndexFile() { 108 return this.diskIndex == null ? null : this.diskIndex.indexFile; 109 } 110 public boolean hasChanged() { 111 return this.memoryIndex.hasChanged(); 112 } 113 118 public EntryResult[] query(char[][] categories, char[] key, int matchRule) throws IOException { 119 if (this.memoryIndex.shouldMerge() && monitor.exitReadEnterWrite()) { 120 try { 121 save(); 122 } finally { 123 monitor.exitWriteEnterRead(); 124 } 125 } 126 127 HashtableOfObject results; 128 int rule = matchRule & MATCH_RULE_INDEX_MASK; 129 if (this.memoryIndex.hasChanged()) { 130 results = this.diskIndex.addQueryResults(categories, key, rule, this.memoryIndex); 131 results = this.memoryIndex.addQueryResults(categories, key, rule, results); 132 } else { 133 results = this.diskIndex.addQueryResults(categories, key, rule, null); 134 } 135 if (results == null) return null; 136 137 EntryResult[] entryResults = new EntryResult[results.elementSize]; 138 int count = 0; 139 Object [] values = results.valueTable; 140 for (int i = 0, l = values.length; i < l; i++) { 141 EntryResult result = (EntryResult) values[i]; 142 if (result != null) 143 entryResults[count++] = result; 144 } 145 return entryResults; 146 } 147 150 public String [] queryDocumentNames(String substring) throws IOException { 151 SimpleSet results; 152 if (this.memoryIndex.hasChanged()) { 153 results = this.diskIndex.addDocumentNames(substring, this.memoryIndex); 154 this.memoryIndex.addDocumentNames(substring, results); 155 } else { 156 results = this.diskIndex.addDocumentNames(substring, null); 157 } 158 if (results.elementSize == 0) return null; 159 160 String [] documentNames = new String [results.elementSize]; 161 int count = 0; 162 Object [] paths = results.values; 163 for (int i = 0, l = paths.length; i < l; i++) 164 if (paths[i] != null) 165 documentNames[count++] = (String ) paths[i]; 166 return documentNames; 167 } 168 public void remove(String containerRelativePath) { 169 this.memoryIndex.remove(containerRelativePath); 170 } 171 public void save() throws IOException { 172 if (!hasChanged()) return; 174 175 int numberOfChanges = this.memoryIndex.docsToReferences.elementSize; 176 this.diskIndex = this.diskIndex.mergeWith(this.memoryIndex); 177 this.memoryIndex = new MemoryIndex(); 178 if (numberOfChanges > 1000) 179 System.gc(); } 181 public void startQuery() { 182 if (this.diskIndex != null) 183 this.diskIndex.startQuery(); 184 } 185 public void stopQuery() { 186 if (this.diskIndex != null) 187 this.diskIndex.stopQuery(); 188 } 189 public String toString() { 190 return "Index for " + this.containerPath; } 192 } 193 | Popular Tags |