1
2
3
4
5 package javax.jmdns.impl;
6
7 import java.io.ByteArrayOutputStream;
8 import java.io.DataOutputStream;
9 import java.io.IOException;
10 import java.util.Collections;
11 import java.util.Map;
12
13 import javax.jmdns.ServiceInfo.Fields;
14 import javax.jmdns.impl.constants.DNSRecordClass;
15 import javax.jmdns.impl.constants.DNSRecordType;
16
17
18
19
20
21
22 public abstract class DNSEntry {
23
24 private final String _key;
25
26 private final String _name;
27
28 private final String _type;
29
30 private final DNSRecordType _recordType;
31
32 private final DNSRecordClass _dnsClass;
33
34 private final boolean _unique;
35
36 final Map<Fields, String> _qualifiedNameMap;
37
38
39
40
41 DNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
42 _name = name;
43
44 _recordType = type;
45 _dnsClass = recordClass;
46 _unique = unique;
47 _qualifiedNameMap = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getName());
48 String domain = _qualifiedNameMap.get(Fields.Domain);
49 String protocol = _qualifiedNameMap.get(Fields.Protocol);
50 String application = _qualifiedNameMap.get(Fields.Application);
51 String instance = _qualifiedNameMap.get(Fields.Instance).toLowerCase();
52 _type = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
53 _key = ((instance.length() > 0 ? instance + "." : "") + _type).toLowerCase();
54 }
55
56
57
58
59
60 @Override
61 public boolean equals(Object obj) {
62 boolean result = false;
63 if (obj instanceof DNSEntry) {
64 DNSEntry other = (DNSEntry) obj;
65 result = this.getKey().equals(other.getKey()) && this.getRecordType().equals(other.getRecordType()) && this.getRecordClass() == other.getRecordClass();
66 }
67 return result;
68 }
69
70
71
72
73
74
75
76 public boolean isSameEntry(DNSEntry entry) {
77 return this.getKey().equals(entry.getKey()) && this.getRecordType().equals(entry.getRecordType()) && ((DNSRecordClass.CLASS_ANY == entry.getRecordClass()) || this.getRecordClass().equals(entry.getRecordClass()));
78 }
79
80
81
82
83
84
85
86 public boolean sameSubtype(DNSEntry other) {
87 return this.getSubtype().equals(other.getSubtype());
88 }
89
90
91
92
93
94
95 public String getSubtype() {
96 String subtype = this.getQualifiedNameMap().get(Fields.Subtype);
97 return (subtype != null ? subtype : "");
98 }
99
100
101
102
103
104
105 public String getName() {
106 return (_name != null ? _name : "");
107 }
108
109
110
111
112 public String getType() {
113 return (_type != null ? _type : "");
114 }
115
116
117
118
119
120
121 public String getKey() {
122 return (_key != null ? _key : "");
123 }
124
125
126
127
128 public DNSRecordType getRecordType() {
129 return (_recordType != null ? _recordType : DNSRecordType.TYPE_IGNORE);
130 }
131
132
133
134
135 public DNSRecordClass getRecordClass() {
136 return (_dnsClass != null ? _dnsClass : DNSRecordClass.CLASS_UNKNOWN);
137 }
138
139
140
141
142 public boolean isUnique() {
143 return _unique;
144 }
145
146 public Map<Fields, String> getQualifiedNameMap() {
147 return Collections.unmodifiableMap(_qualifiedNameMap);
148 }
149
150 public boolean isServicesDiscoveryMetaQuery() {
151 return _qualifiedNameMap.get(Fields.Application).equals("dns-sd") && _qualifiedNameMap.get(Fields.Instance).equals("_services");
152 }
153
154 public boolean isDomainDiscoveryQuery() {
155
156
157
158
159
160
161 if (_qualifiedNameMap.get(Fields.Application).equals("dns-sd")) {
162 String name = _qualifiedNameMap.get(Fields.Instance);
163 return "b".equals(name) || "db".equals(name) || "r".equals(name) || "dr".equals(name) || "lb".equals(name);
164 }
165 return false;
166 }
167
168 public boolean isReverseLookup() {
169 return this.isV4ReverseLookup() || this.isV6ReverseLookup();
170 }
171
172 public boolean isV4ReverseLookup() {
173 return _qualifiedNameMap.get(Fields.Domain).endsWith("in-addr.arpa");
174 }
175
176 public boolean isV6ReverseLookup() {
177 return _qualifiedNameMap.get(Fields.Domain).endsWith("ip6.arpa");
178 }
179
180
181
182
183
184
185
186
187 public abstract boolean isStale(long now);
188
189
190
191
192
193
194
195
196 public abstract boolean isExpired(long now);
197
198
199
200
201
202
203
204 public boolean isSameRecordClass(DNSEntry entry) {
205 return (entry != null) && (entry.getRecordClass() == this.getRecordClass());
206 }
207
208
209
210
211
212
213
214 public boolean isSameType(DNSEntry entry) {
215 return (entry != null) && (entry.getRecordType() == this.getRecordType());
216 }
217
218
219
220
221
222 protected void toByteArray(DataOutputStream dout) throws IOException {
223 dout.write(this.getName().getBytes("UTF8"));
224 dout.writeShort(this.getRecordType().indexValue());
225 dout.writeShort(this.getRecordClass().indexValue());
226 }
227
228
229
230
231
232
233 protected byte[] toByteArray() {
234 try {
235 ByteArrayOutputStream bout = new ByteArrayOutputStream();
236 DataOutputStream dout = new DataOutputStream(bout);
237 this.toByteArray(dout);
238 dout.close();
239 return bout.toByteArray();
240 } catch (IOException e) {
241 throw new InternalError();
242 }
243 }
244
245
246
247
248
249
250
251 public int compareTo(DNSEntry that) {
252 byte[] thisBytes = this.toByteArray();
253 byte[] thatBytes = that.toByteArray();
254 for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++) {
255 if (thisBytes[i] > thatBytes[i]) {
256 return 1;
257 } else if (thisBytes[i] < thatBytes[i]) {
258 return -1;
259 }
260 }
261 return thisBytes.length - thatBytes.length;
262 }
263
264
265
266
267 @Override
268 public int hashCode() {
269 return this.getKey().hashCode() + this.getRecordType().indexValue() + this.getRecordClass().indexValue();
270 }
271
272
273
274
275
276 @Override
277 public String toString() {
278 StringBuilder aLog = new StringBuilder(200);
279 aLog.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this));
280 aLog.append(" type: " + this.getRecordType());
281 aLog.append(", class: " + this.getRecordClass());
282 aLog.append((_unique ? "-unique," : ","));
283 aLog.append(" name: " + _name);
284 this.toString(aLog);
285 aLog.append("]");
286 return aLog.toString();
287 }
288
289
290
291
292 protected void toString(StringBuilder aLog) {
293
294 }
295
296 }