$search
00001 // Copyright 2003-2005 Arthur van Hoff Rick Blair 00002 // Licensed under Apache License version 2.0 00003 // Original license LGPL 00004 00005 package javax.jmdns.impl; 00006 00007 import java.util.AbstractMap; 00008 import java.util.ArrayList; 00009 import java.util.Collection; 00010 import java.util.Collections; 00011 import java.util.HashSet; 00012 import java.util.Iterator; 00013 import java.util.List; 00014 import java.util.Map; 00015 import java.util.Set; 00016 00017 import javax.jmdns.impl.constants.DNSRecordClass; 00018 import javax.jmdns.impl.constants.DNSRecordType; 00019 00045 public class DNSCache extends AbstractMap<String, List<? extends DNSEntry>> { 00046 00047 // private static Logger logger = Logger.getLogger(DNSCache.class.getName()); 00048 00049 private transient Set<Map.Entry<String, List<? extends DNSEntry>>> _entrySet = null; 00050 00054 public static final DNSCache EmptyCache = new _EmptyCache(); 00055 00056 static final class _EmptyCache extends DNSCache { 00057 00061 @Override 00062 public int size() { 00063 return 0; 00064 } 00065 00069 @Override 00070 public boolean isEmpty() { 00071 return true; 00072 } 00073 00077 @Override 00078 public boolean containsKey(Object key) { 00079 return false; 00080 } 00081 00085 @Override 00086 public boolean containsValue(Object value) { 00087 return false; 00088 } 00089 00093 @Override 00094 public List<DNSEntry> get(Object key) { 00095 return null; 00096 } 00097 00101 @Override 00102 public Set<String> keySet() { 00103 return Collections.emptySet(); 00104 } 00105 00109 @Override 00110 public Collection<List<? extends DNSEntry>> values() { 00111 return Collections.emptySet(); 00112 } 00113 00117 @Override 00118 public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() { 00119 return Collections.emptySet(); 00120 } 00121 00125 @Override 00126 public boolean equals(Object o) { 00127 return (o instanceof Map) && ((Map<?, ?>) o).size() == 0; 00128 } 00129 00133 @Override 00134 public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) { 00135 return null; 00136 } 00137 00141 @Override 00142 public int hashCode() { 00143 return 0; 00144 } 00145 00146 } 00147 00151 protected static class _CacheEntry extends Object implements Map.Entry<String, List<? extends DNSEntry>> { 00152 00153 private List<? extends DNSEntry> _value; 00154 00155 private String _key; 00156 00161 protected _CacheEntry(String key, List<? extends DNSEntry> value) { 00162 super(); 00163 _key = (key != null ? key.trim().toLowerCase() : null); 00164 _value = value; 00165 } 00166 00170 protected _CacheEntry(Map.Entry<String, List<? extends DNSEntry>> entry) { 00171 super(); 00172 if (entry instanceof _CacheEntry) { 00173 _key = ((_CacheEntry) entry).getKey(); 00174 _value = ((_CacheEntry) entry).getValue(); 00175 } 00176 } 00177 00181 @Override 00182 public String getKey() { 00183 return (_key != null ? _key : ""); 00184 } 00185 00189 @Override 00190 public List<? extends DNSEntry> getValue() { 00191 return _value; 00192 } 00193 00197 @Override 00198 public List<? extends DNSEntry> setValue(List<? extends DNSEntry> value) { 00199 List<? extends DNSEntry> oldValue = _value; 00200 _value = value; 00201 return oldValue; 00202 } 00203 00209 public boolean isEmpty() { 00210 return this.getValue().isEmpty(); 00211 } 00212 00216 @Override 00217 public boolean equals(Object entry) { 00218 if (!(entry instanceof Map.Entry)) { 00219 return false; 00220 } 00221 return this.getKey().equals(((Map.Entry<?, ?>) entry).getKey()) && this.getValue().equals(((Map.Entry<?, ?>) entry).getValue()); 00222 } 00223 00227 @Override 00228 public int hashCode() { 00229 return (_key == null ? 0 : _key.hashCode()); 00230 } 00231 00235 @Override 00236 public synchronized String toString() { 00237 StringBuffer aLog = new StringBuffer(200); 00238 aLog.append("\n\t\tname '"); 00239 aLog.append(_key); 00240 aLog.append("' "); 00241 if ((_value != null) && (!_value.isEmpty())) { 00242 for (DNSEntry entry : _value) { 00243 aLog.append("\n\t\t\t"); 00244 aLog.append(entry.toString()); 00245 } 00246 } else { 00247 aLog.append(" no entries"); 00248 } 00249 return aLog.toString(); 00250 } 00251 } 00252 00256 public DNSCache() { 00257 this(1024); 00258 } 00259 00263 public DNSCache(DNSCache map) { 00264 this(map != null ? map.size() : 1024); 00265 if (map != null) { 00266 this.putAll(map); 00267 } 00268 } 00269 00275 public DNSCache(int initialCapacity) { 00276 super(); 00277 _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>(initialCapacity); 00278 } 00279 00280 // ==================================================================== 00281 // Map 00282 00283 /* 00284 * (non-Javadoc) 00285 * @see java.util.AbstractMap#entrySet() 00286 */ 00287 @Override 00288 public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() { 00289 if (_entrySet == null) { 00290 _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>(); 00291 } 00292 return _entrySet; 00293 } 00294 00299 protected Map.Entry<String, List<? extends DNSEntry>> getEntry(String key) { 00300 String stringKey = (key != null ? key.trim().toLowerCase() : null); 00301 for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) { 00302 if (stringKey != null) { 00303 if (stringKey.equals(entry.getKey())) { 00304 return entry; 00305 } 00306 } else { 00307 if (entry.getKey() == null) { 00308 return entry; 00309 } 00310 } 00311 } 00312 return null; 00313 } 00314 00318 @Override 00319 public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) { 00320 synchronized (this) { 00321 List<? extends DNSEntry> oldValue = null; 00322 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(key); 00323 if (oldEntry != null) { 00324 oldValue = oldEntry.setValue(value); 00325 } else { 00326 this.entrySet().add(new _CacheEntry(key, value)); 00327 } 00328 return oldValue; 00329 } 00330 } 00331 00335 @Override 00336 protected Object clone() throws CloneNotSupportedException { 00337 return new DNSCache(this); 00338 } 00339 00340 // ==================================================================== 00341 00347 public synchronized Collection<DNSEntry> allValues() { 00348 List<DNSEntry> allValues = new ArrayList<DNSEntry>(); 00349 for (List<? extends DNSEntry> entry : this.values()) { 00350 if (entry != null) { 00351 allValues.addAll(entry); 00352 } 00353 } 00354 return allValues; 00355 } 00356 00363 public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name) { 00364 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name); 00365 if (entryList != null) { 00366 entryList = new ArrayList<DNSEntry>(entryList); 00367 } else { 00368 entryList = Collections.emptyList(); 00369 } 00370 return entryList; 00371 } 00372 00373 private Collection<? extends DNSEntry> _getDNSEntryList(String name) { 00374 return this.get(name != null ? name.toLowerCase() : null); 00375 } 00376 00383 public synchronized DNSEntry getDNSEntry(DNSEntry dnsEntry) { 00384 DNSEntry result = null; 00385 if (dnsEntry != null) { 00386 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(dnsEntry.getKey()); 00387 if (entryList != null) { 00388 for (DNSEntry testDNSEntry : entryList) { 00389 if (testDNSEntry.isSameEntry(dnsEntry)) { 00390 result = testDNSEntry; 00391 break; 00392 } 00393 } 00394 } 00395 } 00396 return result; 00397 } 00398 00407 public synchronized DNSEntry getDNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass) { 00408 DNSEntry result = null; 00409 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name); 00410 if (entryList != null) { 00411 for (DNSEntry testDNSEntry : entryList) { 00412 if (testDNSEntry.getRecordType().equals(type) && ((DNSRecordClass.CLASS_ANY == recordClass) || testDNSEntry.getRecordClass().equals(recordClass))) { 00413 result = testDNSEntry; 00414 break; 00415 } 00416 } 00417 } 00418 return result; 00419 } 00420 00429 public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name, DNSRecordType type, DNSRecordClass recordClass) { 00430 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name); 00431 if (entryList != null) { 00432 entryList = new ArrayList<DNSEntry>(entryList); 00433 for (Iterator<? extends DNSEntry> i = entryList.iterator(); i.hasNext();) { 00434 DNSEntry testDNSEntry = i.next(); 00435 if (!testDNSEntry.getRecordType().equals(type) || ((DNSRecordClass.CLASS_ANY != recordClass) && !testDNSEntry.getRecordClass().equals(recordClass))) { 00436 i.remove(); 00437 } 00438 } 00439 } else { 00440 entryList = Collections.emptyList(); 00441 } 00442 return entryList; 00443 } 00444 00451 public synchronized boolean addDNSEntry(final DNSEntry dnsEntry) { 00452 boolean result = false; 00453 if (dnsEntry != null) { 00454 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(dnsEntry.getKey()); 00455 00456 List<DNSEntry> aNewValue = null; 00457 if (oldEntry != null) { 00458 aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue()); 00459 } else { 00460 aNewValue = new ArrayList<DNSEntry>(); 00461 } 00462 aNewValue.add(dnsEntry); 00463 00464 if (oldEntry != null) { 00465 oldEntry.setValue(aNewValue); 00466 } else { 00467 this.entrySet().add(new _CacheEntry(dnsEntry.getKey(), aNewValue)); 00468 } 00469 // This is probably not very informative 00470 result = true; 00471 } 00472 return result; 00473 } 00474 00481 public synchronized boolean removeDNSEntry(DNSEntry dnsEntry) { 00482 boolean result = false; 00483 if (dnsEntry != null) { 00484 Map.Entry<String, List<? extends DNSEntry>> existingEntry = this.getEntry(dnsEntry.getKey()); 00485 if (existingEntry != null) { 00486 result = existingEntry.getValue().remove(dnsEntry); 00487 // If we just removed the last one we need to get rid of the entry 00488 if (existingEntry.getValue().isEmpty()) { 00489 this.entrySet().remove(existingEntry); 00490 } 00491 } 00492 } 00493 return result; 00494 } 00495 00504 public synchronized boolean replaceDNSEntry(DNSEntry newDNSEntry, DNSEntry existingDNSEntry) { 00505 boolean result = false; 00506 if ((newDNSEntry != null) && (existingDNSEntry != null) && (newDNSEntry.getKey().equals(existingDNSEntry.getKey()))) { 00507 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(newDNSEntry.getKey()); 00508 00509 List<DNSEntry> aNewValue = null; 00510 if (oldEntry != null) { 00511 aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue()); 00512 } else { 00513 aNewValue = new ArrayList<DNSEntry>(); 00514 } 00515 aNewValue.remove(existingDNSEntry); 00516 aNewValue.add(newDNSEntry); 00517 00518 if (oldEntry != null) { 00519 oldEntry.setValue(aNewValue); 00520 } else { 00521 this.entrySet().add(new _CacheEntry(newDNSEntry.getKey(), aNewValue)); 00522 } 00523 // This is probably not very informative 00524 result = true; 00525 } 00526 return result; 00527 } 00528 00532 @Override 00533 public synchronized String toString() { 00534 StringBuffer aLog = new StringBuffer(2000); 00535 aLog.append("\t---- cache ----"); 00536 for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) { 00537 aLog.append("\n\t\t"); 00538 aLog.append(entry.toString()); 00539 } 00540 return aLog.toString(); 00541 } 00542 00543 }