1
2
3
4 package javax.jmdns.impl;
5
6 import java.util.EventListener;
7 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.ConcurrentMap;
9 import java.util.logging.Logger;
10
11 import javax.jmdns.JmDNS;
12 import javax.jmdns.ServiceEvent;
13 import javax.jmdns.ServiceInfo;
14 import javax.jmdns.ServiceListener;
15 import javax.jmdns.ServiceTypeListener;
16
17
18
19
20
21
22
23
24 public class ListenerStatus<T extends EventListener> {
25
26 public static class ServiceListenerStatus extends ListenerStatus<ServiceListener> {
27 private static Logger logger = Logger.getLogger(ServiceListenerStatus.class.getName());
28
29 private final ConcurrentMap<String, ServiceInfo> _addedServices;
30
31
32
33
34
35
36
37 public ServiceListenerStatus(ServiceListener listener, boolean synch) {
38 super(listener, synch);
39 _addedServices = new ConcurrentHashMap<String, ServiceInfo>(32);
40 }
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 void serviceAdded(ServiceEvent event) {
58 String qualifiedName = event.getName() + "." + event.getType();
59 if (null == _addedServices.putIfAbsent(qualifiedName, event.getInfo().clone())) {
60 this.getListener().serviceAdded(event);
61 ServiceInfo info = event.getInfo();
62 if ((info != null) && (info.hasData())) {
63 this.getListener().serviceResolved(event);
64 }
65 } else {
66 logger.finer("Service Added called for a service already added: " + event);
67 }
68 }
69
70
71
72
73
74
75
76 void serviceRemoved(ServiceEvent event) {
77 String qualifiedName = event.getName() + "." + event.getType();
78 if (_addedServices.remove(qualifiedName, _addedServices.get(qualifiedName))) {
79 this.getListener().serviceRemoved(event);
80 } else {
81 logger.finer("Service Removed called for a service already removed: " + event);
82 }
83 }
84
85
86
87
88
89
90
91
92 synchronized void serviceResolved(ServiceEvent event) {
93 ServiceInfo info = event.getInfo();
94 if ((info != null) && (info.hasData())) {
95 String qualifiedName = event.getName() + "." + event.getType();
96 ServiceInfo previousServiceInfo = _addedServices.get(qualifiedName);
97 if (!_sameInfo(info, previousServiceInfo)) {
98 if (null == previousServiceInfo) {
99 if (null == _addedServices.putIfAbsent(qualifiedName, info.clone())) {
100 this.getListener().serviceResolved(event);
101 }
102 } else {
103 if (_addedServices.replace(qualifiedName, previousServiceInfo, info.clone())) {
104 this.getListener().serviceResolved(event);
105 }
106 }
107 } else {
108 logger.finer("Service Resolved called for a service already resolved: " + event);
109 }
110 } else {
111 logger.warning("Service Resolved called for an unresolved event: " + event);
112
113 }
114 }
115
116 private static final boolean _sameInfo(ServiceInfo info, ServiceInfo lastInfo) {
117 if (info == null) return false;
118 if (lastInfo == null) return false;
119 if (!info.equals(lastInfo)) return false;
120 byte[] text = info.getTextBytes();
121 byte[] lastText = lastInfo.getTextBytes();
122 if (text.length != lastText.length) return false;
123 for (int i = 0; i < text.length; i++) {
124 if (text[i] != lastText[i]) return false;
125 }
126 return true;
127 }
128
129
130
131
132
133 @Override
134 public String toString() {
135 StringBuilder aLog = new StringBuilder(2048);
136 aLog.append("[Status for ");
137 aLog.append(this.getListener().toString());
138 if (_addedServices.isEmpty()) {
139 aLog.append(" no type event ");
140 } else {
141 aLog.append(" (");
142 for (String service : _addedServices.keySet()) {
143 aLog.append(service + ", ");
144 }
145 aLog.append(") ");
146 }
147 aLog.append("]");
148 return aLog.toString();
149 }
150
151 }
152
153 public static class ServiceTypeListenerStatus extends ListenerStatus<ServiceTypeListener> {
154 private static Logger logger = Logger.getLogger(ServiceTypeListenerStatus.class.getName());
155
156 private final ConcurrentMap<String, String> _addedTypes;
157
158
159
160
161
162
163
164 public ServiceTypeListenerStatus(ServiceTypeListener listener, boolean synch) {
165 super(listener, synch);
166 _addedTypes = new ConcurrentHashMap<String, String>(32);
167 }
168
169
170
171
172
173
174
175 void serviceTypeAdded(ServiceEvent event) {
176 if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
177 this.getListener().serviceTypeAdded(event);
178 } else {
179 logger.finest("Service Type Added called for a service type already added: " + event);
180 }
181 }
182
183
184
185
186
187
188
189
190
191
192
193 void subTypeForServiceTypeAdded(ServiceEvent event) {
194 if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
195 this.getListener().subTypeForServiceTypeAdded(event);
196 } else {
197 logger.finest("Service Sub Type Added called for a service sub type already added: " + event);
198 }
199 }
200
201
202
203
204
205 @Override
206 public String toString() {
207 StringBuilder aLog = new StringBuilder(2048);
208 aLog.append("[Status for ");
209 aLog.append(this.getListener().toString());
210 if (_addedTypes.isEmpty()) {
211 aLog.append(" no type event ");
212 } else {
213 aLog.append(" (");
214 for (String type : _addedTypes.keySet()) {
215 aLog.append(type + ", ");
216 }
217 aLog.append(") ");
218 }
219 aLog.append("]");
220 return aLog.toString();
221 }
222
223 }
224
225 public final static boolean SYNCHONEOUS = true;
226 public final static boolean ASYNCHONEOUS = false;
227
228 private final T _listener;
229
230 private final boolean _synch;
231
232
233
234
235
236
237
238 public ListenerStatus(T listener, boolean synch) {
239 super();
240 _listener = listener;
241 _synch = synch;
242 }
243
244
245
246
247 public T getListener() {
248 return _listener;
249 }
250
251
252
253
254
255
256 public boolean isSynchronous() {
257 return _synch;
258 }
259
260
261
262
263
264 @Override
265 public int hashCode() {
266 return this.getListener().hashCode();
267 }
268
269
270
271
272
273 @Override
274 public boolean equals(Object obj) {
275 return (obj instanceof ListenerStatus) && this.getListener().equals(((ListenerStatus<?>) obj).getListener());
276 }
277
278
279
280
281
282 @Override
283 public String toString() {
284 return "[Status for " + this.getListener().toString() + "]";
285 }
286 }