1
2
3
4
5 package javax.jmdns.impl;
6
7 import java.util.AbstractMap;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import javax.jmdns.impl.constants.DNSRecordClass;
18 import javax.jmdns.impl.constants.DNSRecordType;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class DNSCache extends AbstractMap<String, List<? extends DNSEntry>> {
46
47
48
49 private transient Set<Map.Entry<String, List<? extends DNSEntry>>> _entrySet = null;
50
51
52
53
54 public static final DNSCache EmptyCache = new _EmptyCache();
55
56 static final class _EmptyCache extends DNSCache {
57
58
59
60
61 @Override
62 public int size() {
63 return 0;
64 }
65
66
67
68
69 @Override
70 public boolean isEmpty() {
71 return true;
72 }
73
74
75
76
77 @Override
78 public boolean containsKey(Object key) {
79 return false;
80 }
81
82
83
84
85 @Override
86 public boolean containsValue(Object value) {
87 return false;
88 }
89
90
91
92
93 @Override
94 public List<DNSEntry> get(Object key) {
95 return null;
96 }
97
98
99
100
101 @Override
102 public Set<String> keySet() {
103 return Collections.emptySet();
104 }
105
106
107
108
109 @Override
110 public Collection<List<? extends DNSEntry>> values() {
111 return Collections.emptySet();
112 }
113
114
115
116
117 @Override
118 public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() {
119 return Collections.emptySet();
120 }
121
122
123
124
125 @Override
126 public boolean equals(Object o) {
127 return (o instanceof Map) && ((Map<?, ?>) o).size() == 0;
128 }
129
130
131
132
133 @Override
134 public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) {
135 return null;
136 }
137
138
139
140
141 @Override
142 public int hashCode() {
143 return 0;
144 }
145
146 }
147
148
149
150
151 protected static class _CacheEntry extends Object implements Map.Entry<String, List<? extends DNSEntry>> {
152
153 private List<? extends DNSEntry> _value;
154
155 private String _key;
156
157
158
159
160
161 protected _CacheEntry(String key, List<? extends DNSEntry> value) {
162 super();
163 _key = (key != null ? key.trim().toLowerCase() : null);
164 _value = value;
165 }
166
167
168
169
170 protected _CacheEntry(Map.Entry<String, List<? extends DNSEntry>> entry) {
171 super();
172 if (entry instanceof _CacheEntry) {
173 _key = ((_CacheEntry) entry).getKey();
174 _value = ((_CacheEntry) entry).getValue();
175 }
176 }
177
178
179
180
181 @Override
182 public String getKey() {
183 return (_key != null ? _key : "");
184 }
185
186
187
188
189 @Override
190 public List<? extends DNSEntry> getValue() {
191 return _value;
192 }
193
194
195
196
197 @Override
198 public List<? extends DNSEntry> setValue(List<? extends DNSEntry> value) {
199 List<? extends DNSEntry> oldValue = _value;
200 _value = value;
201 return oldValue;
202 }
203
204
205
206
207
208
209 public boolean isEmpty() {
210 return this.getValue().isEmpty();
211 }
212
213
214
215
216 @Override
217 public boolean equals(Object entry) {
218 if (!(entry instanceof Map.Entry)) {
219 return false;
220 }
221 return this.getKey().equals(((Map.Entry<?, ?>) entry).getKey()) && this.getValue().equals(((Map.Entry<?, ?>) entry).getValue());
222 }
223
224
225
226
227 @Override
228 public int hashCode() {
229 return (_key == null ? 0 : _key.hashCode());
230 }
231
232
233
234
235 @Override
236 public synchronized String toString() {
237 StringBuffer aLog = new StringBuffer(200);
238 aLog.append("\n\t\tname '");
239 aLog.append(_key);
240 aLog.append("' ");
241 if ((_value != null) && (!_value.isEmpty())) {
242 for (DNSEntry entry : _value) {
243 aLog.append("\n\t\t\t");
244 aLog.append(entry.toString());
245 }
246 } else {
247 aLog.append(" no entries");
248 }
249 return aLog.toString();
250 }
251 }
252
253
254
255
256 public DNSCache() {
257 this(1024);
258 }
259
260
261
262
263 public DNSCache(DNSCache map) {
264 this(map != null ? map.size() : 1024);
265 if (map != null) {
266 this.putAll(map);
267 }
268 }
269
270
271
272
273
274
275 public DNSCache(int initialCapacity) {
276 super();
277 _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>(initialCapacity);
278 }
279
280
281
282
283
284
285
286
287 @Override
288 public Set<Map.Entry<String, List<? extends DNSEntry>>> entrySet() {
289 if (_entrySet == null) {
290 _entrySet = new HashSet<Map.Entry<String, List<? extends DNSEntry>>>();
291 }
292 return _entrySet;
293 }
294
295
296
297
298
299 protected Map.Entry<String, List<? extends DNSEntry>> getEntry(String key) {
300 String stringKey = (key != null ? key.trim().toLowerCase() : null);
301 for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) {
302 if (stringKey != null) {
303 if (stringKey.equals(entry.getKey())) {
304 return entry;
305 }
306 } else {
307 if (entry.getKey() == null) {
308 return entry;
309 }
310 }
311 }
312 return null;
313 }
314
315
316
317
318 @Override
319 public List<? extends DNSEntry> put(String key, List<? extends DNSEntry> value) {
320 synchronized (this) {
321 List<? extends DNSEntry> oldValue = null;
322 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(key);
323 if (oldEntry != null) {
324 oldValue = oldEntry.setValue(value);
325 } else {
326 this.entrySet().add(new _CacheEntry(key, value));
327 }
328 return oldValue;
329 }
330 }
331
332
333
334
335 @Override
336 protected Object clone() throws CloneNotSupportedException {
337 return new DNSCache(this);
338 }
339
340
341
342
343
344
345
346
347 public synchronized Collection<DNSEntry> allValues() {
348 List<DNSEntry> allValues = new ArrayList<DNSEntry>();
349 for (List<? extends DNSEntry> entry : this.values()) {
350 if (entry != null) {
351 allValues.addAll(entry);
352 }
353 }
354 return allValues;
355 }
356
357
358
359
360
361
362
363 public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name) {
364 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
365 if (entryList != null) {
366 entryList = new ArrayList<DNSEntry>(entryList);
367 } else {
368 entryList = Collections.emptyList();
369 }
370 return entryList;
371 }
372
373 private Collection<? extends DNSEntry> _getDNSEntryList(String name) {
374 return this.get(name != null ? name.toLowerCase() : null);
375 }
376
377
378
379
380
381
382
383 public synchronized DNSEntry getDNSEntry(DNSEntry dnsEntry) {
384 DNSEntry result = null;
385 if (dnsEntry != null) {
386 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(dnsEntry.getKey());
387 if (entryList != null) {
388 for (DNSEntry testDNSEntry : entryList) {
389 if (testDNSEntry.isSameEntry(dnsEntry)) {
390 result = testDNSEntry;
391 break;
392 }
393 }
394 }
395 }
396 return result;
397 }
398
399
400
401
402
403
404
405
406
407 public synchronized DNSEntry getDNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass) {
408 DNSEntry result = null;
409 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
410 if (entryList != null) {
411 for (DNSEntry testDNSEntry : entryList) {
412 if (testDNSEntry.getRecordType().equals(type) && ((DNSRecordClass.CLASS_ANY == recordClass) || testDNSEntry.getRecordClass().equals(recordClass))) {
413 result = testDNSEntry;
414 break;
415 }
416 }
417 }
418 return result;
419 }
420
421
422
423
424
425
426
427
428
429 public synchronized Collection<? extends DNSEntry> getDNSEntryList(String name, DNSRecordType type, DNSRecordClass recordClass) {
430 Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
431 if (entryList != null) {
432 entryList = new ArrayList<DNSEntry>(entryList);
433 for (Iterator<? extends DNSEntry> i = entryList.iterator(); i.hasNext();) {
434 DNSEntry testDNSEntry = i.next();
435 if (!testDNSEntry.getRecordType().equals(type) || ((DNSRecordClass.CLASS_ANY != recordClass) && !testDNSEntry.getRecordClass().equals(recordClass))) {
436 i.remove();
437 }
438 }
439 } else {
440 entryList = Collections.emptyList();
441 }
442 return entryList;
443 }
444
445
446
447
448
449
450
451 public synchronized boolean addDNSEntry(final DNSEntry dnsEntry) {
452 boolean result = false;
453 if (dnsEntry != null) {
454 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(dnsEntry.getKey());
455
456 List<DNSEntry> aNewValue = null;
457 if (oldEntry != null) {
458 aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue());
459 } else {
460 aNewValue = new ArrayList<DNSEntry>();
461 }
462 aNewValue.add(dnsEntry);
463
464 if (oldEntry != null) {
465 oldEntry.setValue(aNewValue);
466 } else {
467 this.entrySet().add(new _CacheEntry(dnsEntry.getKey(), aNewValue));
468 }
469
470 result = true;
471 }
472 return result;
473 }
474
475
476
477
478
479
480
481 public synchronized boolean removeDNSEntry(DNSEntry dnsEntry) {
482 boolean result = false;
483 if (dnsEntry != null) {
484 Map.Entry<String, List<? extends DNSEntry>> existingEntry = this.getEntry(dnsEntry.getKey());
485 if (existingEntry != null) {
486 result = existingEntry.getValue().remove(dnsEntry);
487
488 if (existingEntry.getValue().isEmpty()) {
489 this.entrySet().remove(existingEntry);
490 }
491 }
492 }
493 return result;
494 }
495
496
497
498
499
500
501
502
503
504 public synchronized boolean replaceDNSEntry(DNSEntry newDNSEntry, DNSEntry existingDNSEntry) {
505 boolean result = false;
506 if ((newDNSEntry != null) && (existingDNSEntry != null) && (newDNSEntry.getKey().equals(existingDNSEntry.getKey()))) {
507 Map.Entry<String, List<? extends DNSEntry>> oldEntry = this.getEntry(newDNSEntry.getKey());
508
509 List<DNSEntry> aNewValue = null;
510 if (oldEntry != null) {
511 aNewValue = new ArrayList<DNSEntry>(oldEntry.getValue());
512 } else {
513 aNewValue = new ArrayList<DNSEntry>();
514 }
515 aNewValue.remove(existingDNSEntry);
516 aNewValue.add(newDNSEntry);
517
518 if (oldEntry != null) {
519 oldEntry.setValue(aNewValue);
520 } else {
521 this.entrySet().add(new _CacheEntry(newDNSEntry.getKey(), aNewValue));
522 }
523
524 result = true;
525 }
526 return result;
527 }
528
529
530
531
532 @Override
533 public synchronized String toString() {
534 StringBuffer aLog = new StringBuffer(2000);
535 aLog.append("\t---- cache ----");
536 for (Map.Entry<String, List<? extends DNSEntry>> entry : this.entrySet()) {
537 aLog.append("\n\t\t");
538 aLog.append(entry.toString());
539 }
540 return aLog.toString();
541 }
542
543 }