1 16 17 package org.apache.xerces.jaxp.validation; 18 19 import java.lang.ref.Reference ; 20 import java.lang.ref.ReferenceQueue ; 21 import java.lang.ref.SoftReference ; 22 23 import org.apache.xerces.xni.grammars.Grammar; 24 import org.apache.xerces.xni.grammars.XMLGrammarDescription; 25 import org.apache.xerces.xni.grammars.XMLSchemaDescription; 26 import org.apache.xerces.xni.grammars.XMLGrammarPool; 27 28 38 final class SoftReferenceGrammarPool implements XMLGrammarPool { 39 40 44 45 protected static final int TABLE_SIZE = 11; 46 47 48 protected static final Grammar [] ZERO_LENGTH_GRAMMAR_ARRAY = new Grammar [0]; 49 50 54 55 protected Entry [] fGrammars = null; 56 57 58 protected boolean fPoolIsLocked; 59 60 61 protected int fGrammarCount = 0; 62 63 64 protected final ReferenceQueue fReferenceQueue = new ReferenceQueue (); 65 66 70 71 public SoftReferenceGrammarPool() { 72 fGrammars = new Entry[TABLE_SIZE]; 73 fPoolIsLocked = false; 74 } 76 77 public SoftReferenceGrammarPool(int initialCapacity) { 78 fGrammars = new Entry[initialCapacity]; 79 fPoolIsLocked = false; 80 } 81 82 86 96 public Grammar [] retrieveInitialGrammarSet (String grammarType) { 97 synchronized (fGrammars) { 98 clean(); 99 return ZERO_LENGTH_GRAMMAR_ARRAY; 104 } 105 } 107 118 public void cacheGrammars(String grammarType, Grammar[] grammars) { 119 if (!fPoolIsLocked) { 120 for (int i = 0; i < grammars.length; ++i) { 121 putGrammar(grammars[i]); 122 } 123 } 124 } 126 140 public Grammar retrieveGrammar(XMLGrammarDescription desc) { 141 return getGrammar(desc); 142 } 144 148 154 public void putGrammar(Grammar grammar) { 155 if (!fPoolIsLocked) { 156 synchronized (fGrammars) { 157 clean(); 158 XMLGrammarDescription desc = grammar.getGrammarDescription(); 159 int hash = hashCode(desc); 160 int index = (hash & 0x7FFFFFFF) % fGrammars.length; 161 for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) { 162 if (entry.hash == hash && equals(entry.desc, desc)) { 163 if (entry.grammar.get() != grammar) { 164 entry.grammar = new SoftGrammarReference(entry, grammar, fReferenceQueue); 165 } 166 return; 167 } 168 } 169 Entry entry = new Entry(hash, index, desc, grammar, fGrammars[index], fReferenceQueue); 171 fGrammars[index] = entry; 172 fGrammarCount++; 173 } 174 } 175 } 177 184 public Grammar getGrammar(XMLGrammarDescription desc) { 185 synchronized (fGrammars) { 186 clean(); 187 int hash = hashCode(desc); 188 int index = (hash & 0x7FFFFFFF) % fGrammars.length; 189 for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) { 190 Grammar tempGrammar = (Grammar) entry.grammar.get(); 191 192 if (tempGrammar == null) { 193 removeEntry(entry); 194 } 195 else if ((entry.hash == hash) && equals(entry.desc, desc)) { 196 return tempGrammar; 197 } 198 } 199 return null; 200 } 201 } 203 212 public Grammar removeGrammar(XMLGrammarDescription desc) { 213 synchronized (fGrammars) { 214 clean(); 215 int hash = hashCode(desc); 216 int index = (hash & 0x7FFFFFFF) % fGrammars.length; 217 for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) { 218 if ((entry.hash == hash) && equals(entry.desc, desc)) { 219 return removeEntry(entry); 220 } 221 } 222 return null; 223 } 224 } 226 234 public boolean containsGrammar(XMLGrammarDescription desc) { 235 synchronized (fGrammars) { 236 clean(); 237 int hash = hashCode(desc); 238 int index = (hash & 0x7FFFFFFF) % fGrammars.length; 239 for (Entry entry = fGrammars[index]; entry != null ; entry = entry.next) { 240 Grammar tempGrammar = (Grammar) entry.grammar.get(); 241 242 if (tempGrammar == null) { 243 removeEntry(entry); 244 } 245 else if ((entry.hash == hash) && equals(entry.desc, desc)) { 246 return true; 247 } 248 } 249 return false; 250 } 251 } 253 256 public void lockPool() { 257 fPoolIsLocked = true; 258 } 260 264 public void unlockPool() { 265 fPoolIsLocked = false; 266 } 268 272 public void clear() { 273 for (int i=0; i<fGrammars.length; i++) { 274 if(fGrammars[i] != null) { 275 fGrammars[i].clear(); 276 fGrammars[i] = null; 277 } 278 } 279 fGrammarCount = 0; 280 } 282 291 public boolean equals(XMLGrammarDescription desc1, XMLGrammarDescription desc2) { 292 if (desc1 instanceof XMLSchemaDescription) { 293 if (!(desc2 instanceof XMLSchemaDescription)) { 294 return false; 295 } 296 final XMLSchemaDescription sd1 = (XMLSchemaDescription) desc1; 297 final XMLSchemaDescription sd2 = (XMLSchemaDescription) desc2; 298 final String targetNamespace = sd1.getTargetNamespace(); 299 if (targetNamespace != null) { 300 if (!targetNamespace.equals(sd2.getTargetNamespace())) { 301 return false; 302 } 303 } 304 else if (sd2.getTargetNamespace() != null) { 305 return false; 306 } 307 final String expandedSystemId = sd1.getExpandedSystemId(); 313 if (expandedSystemId != null) { 314 if (!expandedSystemId.equals(sd2.getExpandedSystemId())) { 315 return false; 316 } 317 } 318 else if (sd2.getExpandedSystemId() != null) { 319 return false; 320 } 321 return true; 322 } 323 return desc1.equals(desc2); 324 } 325 326 332 public int hashCode(XMLGrammarDescription desc) { 333 if (desc instanceof XMLSchemaDescription) { 334 final XMLSchemaDescription sd = (XMLSchemaDescription) desc; 335 final String targetNamespace = sd.getTargetNamespace(); 336 final String expandedSystemId = sd.getExpandedSystemId(); 337 int hash = (targetNamespace != null) ? targetNamespace.hashCode() : 0; 338 hash ^= (expandedSystemId != null) ? expandedSystemId.hashCode() : 0; 339 return hash; 340 } 341 return desc.hashCode(); 342 } 343 344 350 private Grammar removeEntry(Entry entry) { 351 if (entry.prev != null) { 352 entry.prev.next = entry.next; 353 } 354 else { 355 fGrammars[entry.bucket] = entry.next; 356 } 357 if (entry.next != null) { 358 entry.next.prev = entry.prev; 359 } 360 --fGrammarCount; 361 entry.grammar.entry = null; 362 return (Grammar) entry.grammar.get(); 363 } 364 365 368 private void clean() { 369 Reference ref = fReferenceQueue.poll(); 370 while (ref != null) { 371 Entry entry = ((SoftGrammarReference) ref).entry; 372 if (entry != null) { 373 removeEntry(entry); 374 } 375 ref = fReferenceQueue.poll(); 376 } 377 } 378 379 383 static final class Entry { 384 385 public int hash; 386 public int bucket; 387 public Entry prev; 388 public Entry next; 389 public XMLGrammarDescription desc; 390 public SoftGrammarReference grammar; 391 392 protected Entry(int hash, int bucket, XMLGrammarDescription desc, Grammar grammar, Entry next, ReferenceQueue queue) { 393 this.hash = hash; 394 this.bucket = bucket; 395 this.prev = null; 396 this.next = next; 397 if (next != null) { 398 next.prev = this; 399 } 400 this.desc = desc; 401 this.grammar = new SoftGrammarReference(this, grammar, queue); 402 } 403 404 protected void clear () { 407 desc = null; 408 grammar = null; 409 if(next != null) { 410 next.clear(); 411 next = null; 412 } 413 } 415 } 417 421 static final class SoftGrammarReference extends SoftReference { 422 423 public Entry entry; 424 425 protected SoftGrammarReference(Entry entry, Grammar grammar, ReferenceQueue queue) { 426 super(grammar, queue); 427 this.entry = entry; 428 } 429 430 } 432 } | Popular Tags |