1 23 package org.objectweb.joram.shared.util; 24 25 import java.io.*; 26 import java.util.Enumeration ; 27 import java.util.Map ; 28 import java.util.NoSuchElementException ; 29 import java.util.ConcurrentModificationException ; 30 31 import org.objectweb.joram.shared.stream.*; 32 33 import org.objectweb.joram.shared.JoramTracing; 34 import org.objectweb.util.monolog.api.BasicLevel; 35 36 41 public class Properties implements Cloneable { 42 43 private transient int count; 44 45 private transient Entry table[]; 46 47 51 private transient int threshold; 52 53 54 private transient float loadFactor; 55 56 63 private transient int modCount = 0; 64 65 74 public Properties(int initialCapacity, float loadFactor) { 75 if (initialCapacity < 0) 76 throw new IllegalArgumentException ("Illegal Capacity: "+ 77 initialCapacity); 78 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 79 throw new IllegalArgumentException ("Illegal Load: "+loadFactor); 80 81 if (initialCapacity==0) 82 initialCapacity = 1; 83 this.loadFactor = loadFactor; 84 table = new Entry[initialCapacity]; 85 threshold = (int)(initialCapacity * loadFactor); 86 } 87 88 96 public Properties(int initialCapacity) { 97 this(initialCapacity, 0.75f); 98 } 99 100 104 public Properties() { 105 this(11, 0.75f); 106 } 107 108 113 public synchronized int size() { 114 return count; 115 } 116 117 123 public synchronized boolean isEmpty() { 124 return count == 0; 125 } 126 127 136 public synchronized Enumeration keys() { 137 return getEnumeration(KEYS); 138 } 139 140 151 public synchronized Enumeration elements() { 152 return getEnumeration(VALUES); 153 } 154 155 165 public synchronized boolean containsKey(String key) { 166 Entry tab[] = table; 167 int hash = key.hashCode(); 168 int index = (hash & 0x7FFFFFFF) % tab.length; 169 for (Entry e = tab[index] ; e != null ; e = e.next) { 170 if ((e.hash == hash) && e.key.equals(key)) { 171 return true; 172 } 173 } 174 return false; 175 } 176 177 187 public synchronized Object get(String key) { 188 Entry tab[] = table; 189 int hash = key.hashCode(); 190 int index = (hash & 0x7FFFFFFF) % tab.length; 191 for (Entry e = tab[index] ; e != null ; e = e.next) { 192 if ((e.hash == hash) && e.key.equals(key)) { 193 return e.value; 194 } 195 } 196 return null; 197 } 198 199 206 protected void rehash() { 207 int oldCapacity = table.length; 208 Entry oldMap[] = table; 209 210 int newCapacity = oldCapacity * 2 + 1; 211 Entry newMap[] = new Entry[newCapacity]; 212 213 modCount++; 214 threshold = (int)(newCapacity * loadFactor); 215 table = newMap; 216 217 for (int i = oldCapacity ; i-- > 0 ;) { 218 for (Entry old = oldMap[i] ; old != null ; ) { 219 Entry e = old; 220 old = old.next; 221 222 int index = (e.hash & 0x7FFFFFFF) % newCapacity; 223 e.next = newMap[index]; 224 newMap[index] = e; 225 } 226 } 227 } 228 229 246 public synchronized Object put(String key, Object value) { 247 if (value == null) { 249 throw new NullPointerException (); 250 } 251 252 Entry tab[] = table; 254 int hash = key.hashCode(); 255 int index = (hash & 0x7FFFFFFF) % tab.length; 256 for (Entry e = tab[index] ; e != null ; e = e.next) { 257 if ((e.hash == hash) && e.key.equals(key)) { 258 Object old = e.value; 259 e.value = value; 260 return old; 261 } 262 } 263 264 modCount++; 265 if (count >= threshold) { 266 rehash(); 268 269 tab = table; 270 index = (hash & 0x7FFFFFFF) % tab.length; 271 } 272 273 Entry e = new Entry(hash, key, value, tab[index]); 275 tab[index] = e; 276 count++; 277 return null; 278 } 279 280 289 public synchronized Object remove(String key) { 290 Entry tab[] = table; 291 int hash = key.hashCode(); 292 int index = (hash & 0x7FFFFFFF) % tab.length; 293 for (Entry e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { 294 if ((e.hash == hash) && e.key.equals(key)) { 295 modCount++; 296 if (prev != null) { 297 prev.next = e.next; 298 } else { 299 tab[index] = e.next; 300 } 301 count--; 302 Object oldValue = e.value; 303 e.value = null; 304 return oldValue; 305 } 306 } 307 return null; 308 } 309 310 313 public synchronized void clear() { 314 Entry tab[] = table; 315 modCount++; 316 for (int index = tab.length; --index >= 0; ) 317 tab[index] = null; 318 count = 0; 319 } 320 321 328 public synchronized Object clone() { 329 try { 330 Properties t = (Properties) super.clone(); 331 t.table = new Entry[table.length]; 332 for (int i = table.length ; i-- > 0 ; ) { 333 t.table[i] = (table[i] != null) 334 ? (Entry)table[i].clone() : null; 335 } 336 t.modCount = 0; 337 return t; 338 } catch (CloneNotSupportedException e) { 339 throw new InternalError (); 341 } 342 } 343 344 355 public synchronized String toString() { 356 StringBuffer buf = new StringBuffer (); 357 buf.append("(").append(super.toString()); 358 buf.append("}"); 359 return buf.toString(); 360 } 361 362 363 private Enumeration getEnumeration(int type) { 364 if (count == 0) { 365 return emptyEnumerator; 366 } else { 367 return new Enumerator(type, false); 368 } 369 } 370 371 373 380 public synchronized int hashCode() { 381 391 int h = 0; 392 if (count == 0 || loadFactor < 0) 393 return h; 395 loadFactor = -loadFactor; Entry tab[] = table; 397 for (int i = 0; i < tab.length; i++) 398 for (Entry e = tab[i]; e != null; e = e.next) 399 h += e.key.hashCode() ^ e.value.hashCode(); 400 loadFactor = -loadFactor; 402 return h; 403 } 404 405 421 427 435 444 448 458 461 469 470 473 private static class Entry { 474 int hash; 475 String key; 476 Object value; 477 Entry next; 478 479 protected Entry(int hash, String key, Object value, Entry next) { 480 this.hash = hash; 481 this.key = key; 482 this.value = value; 483 this.next = next; 484 } 485 486 protected Object clone() { 487 return new Entry(hash, key, value, 488 (next==null ? null : (Entry)next.clone())); 489 } 490 491 493 public String getKey() { 494 return key; 495 } 496 497 public Object getValue() { 498 return value; 499 } 500 501 public Object setValue(Object value) { 502 if (value == null) 503 throw new NullPointerException (); 504 505 Object oldValue = this.value; 506 this.value = value; 507 return oldValue; 508 } 509 510 public boolean equals(Object o) { 511 if (!(o instanceof Entry)) 512 return false; 513 Entry e = (Entry) o; 514 515 return (key==null ? e.getKey()==null : key.equals(e.getKey())) && 516 (value==null ? e.getValue()==null : value.equals(e.getValue())); 517 } 518 519 public int hashCode() { 520 return hash ^ (value==null ? 0 : value.hashCode()); 521 } 522 523 public String toString() { 524 return key + "=" + value.toString(); 525 } 526 } 527 528 private static final int KEYS = 0; 530 private static final int VALUES = 1; 531 private static final int ENTRIES = 2; 532 533 540 private class Enumerator implements Enumeration { 541 Entry[] table = Properties.this.table; 542 int index = table.length; 543 Entry entry = null; 544 Entry lastReturned = null; 545 int type; 546 547 551 boolean iterator; 552 553 558 protected int expectedModCount = modCount; 559 560 Enumerator(int type, boolean iterator) { 561 this.type = type; 562 this.iterator = iterator; 563 } 564 565 public boolean hasMoreElements() { 566 Entry e = entry; 567 int i = index; 568 Entry t[] = table; 569 570 while (e == null && i > 0) { 571 e = t[--i]; 572 } 573 entry = e; 574 index = i; 575 return e != null; 576 } 577 578 public Object nextElement() { 579 Entry et = entry; 580 int i = index; 581 Entry t[] = table; 582 583 while (et == null && i > 0) { 584 et = t[--i]; 585 } 586 entry = et; 587 index = i; 588 if (et != null) { 589 Entry e = lastReturned = entry; 590 entry = e.next; 591 return type == KEYS ? e.key : (type == VALUES ? e.value : e); 592 } 593 throw new NoSuchElementException ("Properties Enumerator"); 594 } 595 596 public boolean hasNext() { 598 return hasMoreElements(); 599 } 600 601 public Object next() { 602 if (modCount != expectedModCount) 603 throw new ConcurrentModificationException (); 604 return nextElement(); 605 } 606 607 public void remove() { 608 if (!iterator) 609 throw new UnsupportedOperationException (); 610 if (lastReturned == null) 611 throw new IllegalStateException ("Properties Enumerator"); 612 if (modCount != expectedModCount) 613 throw new ConcurrentModificationException (); 614 615 synchronized(Properties.this) { 616 Entry[] tab = Properties.this.table; 617 int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; 618 619 for (Entry e = tab[index], prev = null; e != null; 620 prev = e, e = e.next) { 621 if (e == lastReturned) { 622 modCount++; 623 expectedModCount++; 624 if (prev == null) 625 tab[index] = e.next; 626 else 627 prev.next = e.next; 628 count--; 629 lastReturned = null; 630 return; 631 } 632 } 633 throw new ConcurrentModificationException (); 634 } 635 } 636 } 637 638 private static EmptyEnumerator emptyEnumerator = new EmptyEnumerator(); 639 640 644 private static class EmptyEnumerator implements Enumeration { 645 646 EmptyEnumerator() { 647 } 648 649 public boolean hasMoreElements() { 650 return false; 651 } 652 653 public Object nextElement() { 654 throw new NoSuchElementException ("Properties Enumerator"); 655 } 656 } 657 658 public void copyInto(Map h) { 659 if (count > 0) { 660 for (int index = table.length-1; index >= 0; index--) { 661 Entry entry = table[index]; 662 663 while (entry != null) { 664 h.put(entry.key, entry.value); 665 entry = entry.next; 666 } 667 } 668 } 669 } 670 671 674 675 681 public void writeTo(OutputStream os) throws IOException { 682 StreamUtil.writeTo(count, os); 683 for (int index = table.length-1; index >= 0; index--) { 684 Entry entry = table[index]; 685 686 while (entry != null) { 687 StreamUtil.writeTo(entry.key, os); 688 StreamUtil.writeObjectTo(entry.value, os); 689 entry = entry.next; 690 } 691 } 692 } 693 694 700 public static Properties readFrom(InputStream is) throws IOException { 701 int count = StreamUtil.readIntFrom(is); 702 if (count == -1) return null; 703 704 Properties p = new Properties(((4*count)/3) +1); 705 706 String key; 707 Object value; 708 for (int i=0; i<count; i++) { 709 key = StreamUtil.readStringFrom(is); 710 value = StreamUtil.readObjectFrom(is); 711 p.put(key, value); 712 } 713 714 return p; 715 } 716 } 717 | Popular Tags |