1 /** 2 * 3 */ 4 package javax.jmdns.impl; 5 6 import java.util.Date; 7 import java.util.Timer; 8 import java.util.TimerTask; 9 import java.util.concurrent.ConcurrentHashMap; 10 import java.util.concurrent.ConcurrentMap; 11 import java.util.concurrent.atomic.AtomicReference; 12 13 import javax.jmdns.impl.tasks.RecordReaper; 14 import javax.jmdns.impl.tasks.Responder; 15 import javax.jmdns.impl.tasks.resolver.ServiceInfoResolver; 16 import javax.jmdns.impl.tasks.resolver.ServiceResolver; 17 import javax.jmdns.impl.tasks.resolver.TypeResolver; 18 import javax.jmdns.impl.tasks.state.Announcer; 19 import javax.jmdns.impl.tasks.state.Canceler; 20 import javax.jmdns.impl.tasks.state.Prober; 21 import javax.jmdns.impl.tasks.state.Renewer; 22 23 /** 24 * This class is used by JmDNS to start the various task required to run the DNS discovery. This interface is only there in order to support MANET modifications. 25 * <p> 26 * <b>Note: </b> This is not considered as part of the general public API of JmDNS. 27 * </p> 28 * 29 * @author Pierre Frisch 30 */ 31 public interface DNSTaskStarter { 32 33 /** 34 * DNSTaskStarter.Factory enable the creation of new instance of DNSTaskStarter. 35 */ 36 public static final class Factory { 37 38 private static volatile Factory _instance; 39 private final ConcurrentMap<JmDNSImpl, DNSTaskStarter> _instances; 40 41 /** 42 * This interface defines a delegate to the DNSTaskStarter class to enable subclassing. 43 */ 44 public static interface ClassDelegate { 45 46 /** 47 * Allows the delegate the opportunity to construct and return a different DNSTaskStarter. 48 * 49 * @param jmDNSImpl 50 * jmDNS instance 51 * @return Should return a new DNSTaskStarter Object. 52 * @see #classDelegate() 53 * @see #setClassDelegate(ClassDelegate anObject) 54 */ newDNSTaskStarter(JmDNSImpl jmDNSImpl)55 public DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl); 56 } 57 58 private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>(); 59 Factory()60 private Factory() { 61 super(); 62 _instances = new ConcurrentHashMap<JmDNSImpl, DNSTaskStarter>(20); 63 } 64 65 /** 66 * Assigns <code>delegate</code> as DNSTaskStarter's class delegate. The class delegate is optional. 67 * 68 * @param delegate 69 * The object to set as DNSTaskStarter's class delegate. 70 * @see #classDelegate() 71 * @see DNSTaskStarter.Factory.ClassDelegate 72 */ setClassDelegate(Factory.ClassDelegate delegate)73 public static void setClassDelegate(Factory.ClassDelegate delegate) { 74 _databaseClassDelegate.set(delegate); 75 } 76 77 /** 78 * Returns DNSTaskStarter's class delegate. 79 * 80 * @return DNSTaskStarter's class delegate. 81 * @see #setClassDelegate(ClassDelegate anObject) 82 * @see DNSTaskStarter.Factory.ClassDelegate 83 */ classDelegate()84 public static Factory.ClassDelegate classDelegate() { 85 return _databaseClassDelegate.get(); 86 } 87 88 /** 89 * Returns a new instance of DNSTaskStarter using the class delegate if it exists. 90 * 91 * @param jmDNSImpl 92 * jmDNS instance 93 * @return new instance of DNSTaskStarter 94 */ newDNSTaskStarter(JmDNSImpl jmDNSImpl)95 protected static DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl) { 96 DNSTaskStarter instance = null; 97 Factory.ClassDelegate delegate = _databaseClassDelegate.get(); 98 if (delegate != null) { 99 instance = delegate.newDNSTaskStarter(jmDNSImpl); 100 } 101 return (instance != null ? instance : new DNSTaskStarterImpl(jmDNSImpl)); 102 } 103 104 /** 105 * Return the instance of the DNSTaskStarter Factory. 106 * 107 * @return DNSTaskStarter Factory 108 */ getInstance()109 public static Factory getInstance() { 110 if (_instance == null) { 111 synchronized (DNSTaskStarter.Factory.class) { 112 if (_instance == null) { 113 _instance = new Factory(); 114 } 115 } 116 } 117 return _instance; 118 } 119 120 /** 121 * Return the instance of the DNSTaskStarter for the JmDNS. 122 * 123 * @param jmDNSImpl 124 * jmDNS instance 125 * @return the DNSTaskStarter 126 */ getStarter(JmDNSImpl jmDNSImpl)127 public DNSTaskStarter getStarter(JmDNSImpl jmDNSImpl) { 128 DNSTaskStarter starter = _instances.get(jmDNSImpl); 129 if (starter == null) { 130 _instances.putIfAbsent(jmDNSImpl, newDNSTaskStarter(jmDNSImpl)); 131 starter = _instances.get(jmDNSImpl); 132 } 133 return starter; 134 } 135 136 } 137 138 public static final class DNSTaskStarterImpl implements DNSTaskStarter { 139 140 private final JmDNSImpl _jmDNSImpl; 141 142 /** 143 * The timer is used to dispatch all outgoing messages of JmDNS. It is also used to dispatch maintenance tasks for the DNS cache. 144 */ 145 private final Timer _timer; 146 147 /** 148 * The timer is used to dispatch maintenance tasks for the DNS cache. 149 */ 150 private final Timer _stateTimer; 151 152 public static class StarterTimer extends Timer { 153 154 // This is needed because in some case we cancel the timers before all the task have finished running and in some case they will try to reschedule 155 private volatile boolean _cancelled; 156 157 /** 158 * 159 */ StarterTimer()160 public StarterTimer() { 161 super(); 162 _cancelled = false; 163 } 164 165 /** 166 * @param isDaemon 167 */ StarterTimer(boolean isDaemon)168 public StarterTimer(boolean isDaemon) { 169 super(isDaemon); 170 _cancelled = false; 171 } 172 173 /** 174 * @param name 175 * @param isDaemon 176 */ StarterTimer(String name, boolean isDaemon)177 public StarterTimer(String name, boolean isDaemon) { 178 super(name, isDaemon); 179 _cancelled = false; 180 } 181 182 /** 183 * @param name 184 */ StarterTimer(String name)185 public StarterTimer(String name) { 186 super(name); 187 _cancelled = false; 188 } 189 190 /* 191 * (non-Javadoc) 192 * @see java.util.Timer#cancel() 193 */ 194 @Override cancel()195 public synchronized void cancel() { 196 if (_cancelled) return; 197 _cancelled = true; 198 super.cancel(); 199 } 200 201 /* 202 * (non-Javadoc) 203 * @see java.util.Timer#schedule(java.util.TimerTask, long) 204 */ 205 @Override schedule(TimerTask task, long delay)206 public synchronized void schedule(TimerTask task, long delay) { 207 if (_cancelled) return; 208 super.schedule(task, delay); 209 } 210 211 /* 212 * (non-Javadoc) 213 * @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date) 214 */ 215 @Override schedule(TimerTask task, Date time)216 public synchronized void schedule(TimerTask task, Date time) { 217 if (_cancelled) return; 218 super.schedule(task, time); 219 } 220 221 /* 222 * (non-Javadoc) 223 * @see java.util.Timer#schedule(java.util.TimerTask, long, long) 224 */ 225 @Override schedule(TimerTask task, long delay, long period)226 public synchronized void schedule(TimerTask task, long delay, long period) { 227 if (_cancelled) return; 228 super.schedule(task, delay, period); 229 } 230 231 /* 232 * (non-Javadoc) 233 * @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date, long) 234 */ 235 @Override schedule(TimerTask task, Date firstTime, long period)236 public synchronized void schedule(TimerTask task, Date firstTime, long period) { 237 if (_cancelled) return; 238 super.schedule(task, firstTime, period); 239 } 240 241 /* 242 * (non-Javadoc) 243 * @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long) 244 */ 245 @Override scheduleAtFixedRate(TimerTask task, long delay, long period)246 public synchronized void scheduleAtFixedRate(TimerTask task, long delay, long period) { 247 if (_cancelled) return; 248 super.scheduleAtFixedRate(task, delay, period); 249 } 250 251 /* 252 * (non-Javadoc) 253 * @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, java.util.Date, long) 254 */ 255 @Override scheduleAtFixedRate(TimerTask task, Date firstTime, long period)256 public synchronized void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) { 257 if (_cancelled) return; 258 super.scheduleAtFixedRate(task, firstTime, period); 259 } 260 261 } 262 DNSTaskStarterImpl(JmDNSImpl jmDNSImpl)263 public DNSTaskStarterImpl(JmDNSImpl jmDNSImpl) { 264 super(); 265 _jmDNSImpl = jmDNSImpl; 266 _timer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").Timer", true); 267 _stateTimer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").State.Timer", false); 268 } 269 270 /* 271 * (non-Javadoc) 272 * @see javax.jmdns.impl.DNSTaskStarter#purgeTimer() 273 */ 274 @Override purgeTimer()275 public void purgeTimer() { 276 _timer.purge(); 277 } 278 279 /* 280 * (non-Javadoc) 281 * @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer() 282 */ 283 @Override purgeStateTimer()284 public void purgeStateTimer() { 285 _stateTimer.purge(); 286 } 287 288 /* 289 * (non-Javadoc) 290 * @see javax.jmdns.impl.DNSTaskStarter#cancelTimer() 291 */ 292 @Override cancelTimer()293 public void cancelTimer() { 294 _timer.cancel(); 295 } 296 297 /* 298 * (non-Javadoc) 299 * @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer() 300 */ 301 @Override cancelStateTimer()302 public void cancelStateTimer() { 303 _stateTimer.cancel(); 304 } 305 306 /* 307 * (non-Javadoc) 308 * @see javax.jmdns.impl.DNSTaskStarter#startProber() 309 */ 310 @Override startProber()311 public void startProber() { 312 new Prober(_jmDNSImpl).start(_stateTimer); 313 } 314 315 /* 316 * (non-Javadoc) 317 * @see javax.jmdns.impl.DNSTaskStarter#startAnnouncer() 318 */ 319 @Override startAnnouncer()320 public void startAnnouncer() { 321 new Announcer(_jmDNSImpl).start(_stateTimer); 322 } 323 324 /* 325 * (non-Javadoc) 326 * @see javax.jmdns.impl.DNSTaskStarter#startRenewer() 327 */ 328 @Override startRenewer()329 public void startRenewer() { 330 new Renewer(_jmDNSImpl).start(_stateTimer); 331 } 332 333 /* 334 * (non-Javadoc) 335 * @see javax.jmdns.impl.DNSTaskStarter#startCanceler() 336 */ 337 @Override startCanceler()338 public void startCanceler() { 339 new Canceler(_jmDNSImpl).start(_stateTimer); 340 } 341 342 /* 343 * (non-Javadoc) 344 * @see javax.jmdns.impl.DNSTaskStarter#startReaper() 345 */ 346 @Override startReaper()347 public void startReaper() { 348 new RecordReaper(_jmDNSImpl).start(_timer); 349 } 350 351 /* 352 * (non-Javadoc) 353 * @see javax.jmdns.impl.DNSTaskStarter#startServiceInfoResolver(javax.jmdns.impl.ServiceInfoImpl) 354 */ 355 @Override startServiceInfoResolver(ServiceInfoImpl info)356 public void startServiceInfoResolver(ServiceInfoImpl info) { 357 new ServiceInfoResolver(_jmDNSImpl, info).start(_timer); 358 } 359 360 /* 361 * (non-Javadoc) 362 * @see javax.jmdns.impl.DNSTaskStarter#startTypeResolver() 363 */ 364 @Override startTypeResolver()365 public void startTypeResolver() { 366 new TypeResolver(_jmDNSImpl).start(_timer); 367 } 368 369 /* 370 * (non-Javadoc) 371 * @see javax.jmdns.impl.DNSTaskStarter#startServiceResolver(java.lang.String) 372 */ 373 @Override startServiceResolver(String type)374 public void startServiceResolver(String type) { 375 new ServiceResolver(_jmDNSImpl, type).start(_timer); 376 } 377 378 /* 379 * (non-Javadoc) 380 * @see javax.jmdns.impl.DNSTaskStarter#startResponder(javax.jmdns.impl.DNSIncoming, int) 381 */ 382 @Override startResponder(DNSIncoming in, int port)383 public void startResponder(DNSIncoming in, int port) { 384 new Responder(_jmDNSImpl, in, port).start(_timer); 385 } 386 } 387 388 /** 389 * Purge the general task timer 390 */ purgeTimer()391 public void purgeTimer(); 392 393 /** 394 * Purge the state task timer 395 */ purgeStateTimer()396 public void purgeStateTimer(); 397 398 /** 399 * Cancel the generals task timer 400 */ cancelTimer()401 public void cancelTimer(); 402 403 /** 404 * Cancel the state task timer 405 */ cancelStateTimer()406 public void cancelStateTimer(); 407 408 /** 409 * Start a new prober task 410 */ startProber()411 public void startProber(); 412 413 /** 414 * Start a new announcer task 415 */ startAnnouncer()416 public void startAnnouncer(); 417 418 /** 419 * Start a new renewer task 420 */ startRenewer()421 public void startRenewer(); 422 423 /** 424 * Start a new canceler task 425 */ startCanceler()426 public void startCanceler(); 427 428 /** 429 * Start a new reaper task. There is only supposed to be one reaper running at a time. 430 */ startReaper()431 public void startReaper(); 432 433 /** 434 * Start a new service info resolver task 435 * 436 * @param info 437 * service info to resolve 438 */ startServiceInfoResolver(ServiceInfoImpl info)439 public void startServiceInfoResolver(ServiceInfoImpl info); 440 441 /** 442 * Start a new service type resolver task 443 */ startTypeResolver()444 public void startTypeResolver(); 445 446 /** 447 * Start a new service resolver task 448 * 449 * @param type 450 * service type to resolve 451 */ startServiceResolver(String type)452 public void startServiceResolver(String type); 453 454 /** 455 * Start a new responder task 456 * 457 * @param in 458 * incoming message 459 * @param port 460 * incoming port 461 */ startResponder(DNSIncoming in, int port)462 public void startResponder(DNSIncoming in, int port); 463 464 } 465