blob: ab1720164129126a4edbdb82d85dd3085de0f7f2 [file] [log] [blame]
/**
*
*/
package javax.jmdns.impl;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.tasks.RecordReaper;
import javax.jmdns.impl.tasks.Responder;
import javax.jmdns.impl.tasks.resolver.ServiceInfoResolver;
import javax.jmdns.impl.tasks.resolver.ServiceResolver;
import javax.jmdns.impl.tasks.resolver.TypeResolver;
import javax.jmdns.impl.tasks.state.Announcer;
import javax.jmdns.impl.tasks.state.Canceler;
import javax.jmdns.impl.tasks.state.Prober;
import javax.jmdns.impl.tasks.state.Renewer;
/**
* 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.
* <p>
* <b>Note: </b> This is not considered as part of the general public API of JmDNS.
* </p>
*
* @author Pierre Frisch
*/
public interface DNSTaskStarter {
/**
* DNSTaskStarter.Factory enable the creation of new instance of DNSTaskStarter.
*/
public static final class Factory {
private static volatile Factory _instance;
private final ConcurrentMap<JmDNSImpl, DNSTaskStarter> _instances;
/**
* This interface defines a delegate to the DNSTaskStarter class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different DNSTaskStarter.
*
* @param jmDNSImpl
* jmDNS instance
* @return Should return a new DNSTaskStarter Object.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl);
}
private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
private Factory() {
super();
_instances = new ConcurrentHashMap<JmDNSImpl, DNSTaskStarter>(20);
}
/**
* Assigns <code>delegate</code> as DNSTaskStarter's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as DNSTaskStarter's class delegate.
* @see #classDelegate()
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static void setClassDelegate(Factory.ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns DNSTaskStarter's class delegate.
*
* @return DNSTaskStarter's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static Factory.ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of DNSTaskStarter using the class delegate if it exists.
*
* @param jmDNSImpl
* jmDNS instance
* @return new instance of DNSTaskStarter
*/
protected static DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter instance = null;
Factory.ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
instance = delegate.newDNSTaskStarter(jmDNSImpl);
}
return (instance != null ? instance : new DNSTaskStarterImpl(jmDNSImpl));
}
/**
* Return the instance of the DNSTaskStarter Factory.
*
* @return DNSTaskStarter Factory
*/
public static Factory getInstance() {
if (_instance == null) {
synchronized (DNSTaskStarter.Factory.class) {
if (_instance == null) {
_instance = new Factory();
}
}
}
return _instance;
}
/**
* Return the instance of the DNSTaskStarter for the JmDNS.
*
* @param jmDNSImpl
* jmDNS instance
* @return the DNSTaskStarter
*/
public DNSTaskStarter getStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter starter = _instances.get(jmDNSImpl);
if (starter == null) {
_instances.putIfAbsent(jmDNSImpl, newDNSTaskStarter(jmDNSImpl));
starter = _instances.get(jmDNSImpl);
}
return starter;
}
}
public static final class DNSTaskStarterImpl implements DNSTaskStarter {
private final JmDNSImpl _jmDNSImpl;
/**
* The timer is used to dispatch all outgoing messages of JmDNS. It is also used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _timer;
/**
* The timer is used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _stateTimer;
public static class StarterTimer extends Timer {
// 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
private volatile boolean _cancelled;
/**
*
*/
public StarterTimer() {
super();
_cancelled = false;
}
/**
* @param isDaemon
*/
public StarterTimer(boolean isDaemon) {
super(isDaemon);
_cancelled = false;
}
/**
* @param name
* @param isDaemon
*/
public StarterTimer(String name, boolean isDaemon) {
super(name, isDaemon);
_cancelled = false;
}
/**
* @param name
*/
public StarterTimer(String name) {
super(name);
_cancelled = false;
}
/*
* (non-Javadoc)
* @see java.util.Timer#cancel()
*/
@Override
public synchronized void cancel() {
if (_cancelled) return;
_cancelled = true;
super.cancel();
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay) {
if (_cancelled) return;
super.schedule(task, delay);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
*/
@Override
public synchronized void schedule(TimerTask task, Date time) {
if (_cancelled) return;
super.schedule(task, time);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.schedule(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void schedule(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.schedule(task, firstTime, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, firstTime, period);
}
}
public DNSTaskStarterImpl(JmDNSImpl jmDNSImpl) {
super();
_jmDNSImpl = jmDNSImpl;
_timer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").Timer", true);
_stateTimer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").State.Timer", false);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeTimer()
*/
@Override
public void purgeTimer() {
_timer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer()
*/
@Override
public void purgeStateTimer() {
_stateTimer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelTimer()
*/
@Override
public void cancelTimer() {
_timer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer()
*/
@Override
public void cancelStateTimer() {
_stateTimer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startProber()
*/
@Override
public void startProber() {
new Prober(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startAnnouncer()
*/
@Override
public void startAnnouncer() {
new Announcer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startRenewer()
*/
@Override
public void startRenewer() {
new Renewer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startCanceler()
*/
@Override
public void startCanceler() {
new Canceler(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startReaper()
*/
@Override
public void startReaper() {
new RecordReaper(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceInfoResolver(javax.jmdns.impl.ServiceInfoImpl)
*/
@Override
public void startServiceInfoResolver(ServiceInfoImpl info) {
new ServiceInfoResolver(_jmDNSImpl, info).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startTypeResolver()
*/
@Override
public void startTypeResolver() {
new TypeResolver(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceResolver(java.lang.String)
*/
@Override
public void startServiceResolver(String type) {
new ServiceResolver(_jmDNSImpl, type).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startResponder(javax.jmdns.impl.DNSIncoming, int)
*/
@Override
public void startResponder(DNSIncoming in, int port) {
new Responder(_jmDNSImpl, in, port).start(_timer);
}
}
/**
* Purge the general task timer
*/
public void purgeTimer();
/**
* Purge the state task timer
*/
public void purgeStateTimer();
/**
* Cancel the generals task timer
*/
public void cancelTimer();
/**
* Cancel the state task timer
*/
public void cancelStateTimer();
/**
* Start a new prober task
*/
public void startProber();
/**
* Start a new announcer task
*/
public void startAnnouncer();
/**
* Start a new renewer task
*/
public void startRenewer();
/**
* Start a new canceler task
*/
public void startCanceler();
/**
* Start a new reaper task. There is only supposed to be one reaper running at a time.
*/
public void startReaper();
/**
* Start a new service info resolver task
*
* @param info
* service info to resolve
*/
public void startServiceInfoResolver(ServiceInfoImpl info);
/**
* Start a new service type resolver task
*/
public void startTypeResolver();
/**
* Start a new service resolver task
*
* @param type
* service type to resolve
*/
public void startServiceResolver(String type);
/**
* Start a new responder task
*
* @param in
* incoming message
* @param port
* incoming port
*/
public void startResponder(DNSIncoming in, int port);
}