Home | History | Annotate | Download | only in impl
      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              */
     55             public DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl);
     56         }
     57 
     58         private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
     59 
     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          */
     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          */
     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          */
     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          */
    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          */
    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              */
    160             public StarterTimer() {
    161                 super();
    162                 _cancelled = false;
    163             }
    164 
    165             /**
    166              * @param isDaemon
    167              */
    168             public StarterTimer(boolean isDaemon) {
    169                 super(isDaemon);
    170                 _cancelled = false;
    171             }
    172 
    173             /**
    174              * @param name
    175              * @param isDaemon
    176              */
    177             public StarterTimer(String name, boolean isDaemon) {
    178                 super(name, isDaemon);
    179                 _cancelled = false;
    180             }
    181 
    182             /**
    183              * @param name
    184              */
    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
    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
    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
    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
    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
    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
    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
    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 
    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
    275         public void purgeTimer() {
    276             _timer.purge();
    277         }
    278 
    279         /*
    280          * (non-Javadoc)
    281          * @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer()
    282          */
    283         @Override
    284         public void purgeStateTimer() {
    285             _stateTimer.purge();
    286         }
    287 
    288         /*
    289          * (non-Javadoc)
    290          * @see javax.jmdns.impl.DNSTaskStarter#cancelTimer()
    291          */
    292         @Override
    293         public void cancelTimer() {
    294             _timer.cancel();
    295         }
    296 
    297         /*
    298          * (non-Javadoc)
    299          * @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer()
    300          */
    301         @Override
    302         public void cancelStateTimer() {
    303             _stateTimer.cancel();
    304         }
    305 
    306         /*
    307          * (non-Javadoc)
    308          * @see javax.jmdns.impl.DNSTaskStarter#startProber()
    309          */
    310         @Override
    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
    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
    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
    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
    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
    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
    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
    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
    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      */
    391     public void purgeTimer();
    392 
    393     /**
    394      * Purge the state task timer
    395      */
    396     public void purgeStateTimer();
    397 
    398     /**
    399      * Cancel the generals task timer
    400      */
    401     public void cancelTimer();
    402 
    403     /**
    404      * Cancel the state task timer
    405      */
    406     public void cancelStateTimer();
    407 
    408     /**
    409      * Start a new prober task
    410      */
    411     public void startProber();
    412 
    413     /**
    414      * Start a new announcer task
    415      */
    416     public void startAnnouncer();
    417 
    418     /**
    419      * Start a new renewer task
    420      */
    421     public void startRenewer();
    422 
    423     /**
    424      * Start a new canceler task
    425      */
    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      */
    431     public void startReaper();
    432 
    433     /**
    434      * Start a new service info resolver task
    435      *
    436      * @param info
    437      *            service info to resolve
    438      */
    439     public void startServiceInfoResolver(ServiceInfoImpl info);
    440 
    441     /**
    442      * Start a new service type resolver task
    443      */
    444     public void startTypeResolver();
    445 
    446     /**
    447      * Start a new service resolver task
    448      *
    449      * @param type
    450      *            service type to resolve
    451      */
    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      */
    462     public void startResponder(DNSIncoming in, int port);
    463 
    464 }
    465