use of javax.jmdns.ServiceEvent in project JAirPort by froks.
the class JmDNSImpl method handleServiceResolved.
void handleServiceResolved(ServiceEvent event) {
List<ServiceListenerStatus> list = _serviceListeners.get(event.getType().toLowerCase());
final List<ServiceListenerStatus> listCopy;
if ((list != null) && (!list.isEmpty())) {
if ((event.getInfo() != null) && event.getInfo().hasData()) {
final ServiceEvent localEvent = event;
synchronized (list) {
listCopy = new ArrayList<ServiceListenerStatus>(list);
}
for (final ServiceListenerStatus listener : listCopy) {
_executor.submit(new Runnable() {
/** {@inheritDoc} */
@Override
public void run() {
listener.serviceResolved(localEvent);
}
});
}
}
}
}
use of javax.jmdns.ServiceEvent in project JAirPort by froks.
the class ServiceInfoImpl method updateRecord.
/**
* JmDNS callback to update a DNS record.
*
* @param dnsCache
* @param now
* @param rec
*/
@Override
public void updateRecord(DNSCache dnsCache, long now, DNSEntry rec) {
if ((rec instanceof DNSRecord) && !rec.isExpired(now)) {
boolean serviceUpdated = false;
switch(rec.getRecordType()) {
case // IPv4
TYPE_A:
if (rec.getName().equalsIgnoreCase(this.getServer())) {
_ipv4Addresses.add((Inet4Address) ((DNSRecord.Address) rec).getAddress());
serviceUpdated = true;
}
break;
case // IPv6
TYPE_AAAA:
if (rec.getName().equalsIgnoreCase(this.getServer())) {
_ipv6Addresses.add((Inet6Address) ((DNSRecord.Address) rec).getAddress());
serviceUpdated = true;
}
break;
case TYPE_SRV:
if (rec.getName().equalsIgnoreCase(this.getQualifiedName())) {
DNSRecord.Service srv = (DNSRecord.Service) rec;
boolean serverChanged = (_server == null) || !_server.equalsIgnoreCase(srv.getServer());
_server = srv.getServer();
_port = srv.getPort();
_weight = srv.getWeight();
_priority = srv.getPriority();
if (serverChanged) {
_ipv4Addresses.clear();
_ipv6Addresses.clear();
for (DNSEntry entry : dnsCache.getDNSEntryList(_server, DNSRecordType.TYPE_A, DNSRecordClass.CLASS_IN)) {
this.updateRecord(dnsCache, now, entry);
}
for (DNSEntry entry : dnsCache.getDNSEntryList(_server, DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_IN)) {
this.updateRecord(dnsCache, now, entry);
}
// We do not want to trigger the listener in this case as it will be triggered if the address resolves.
} else {
serviceUpdated = true;
}
}
break;
case TYPE_TXT:
if (rec.getName().equalsIgnoreCase(this.getQualifiedName())) {
DNSRecord.Text txt = (DNSRecord.Text) rec;
_text = txt.getText();
serviceUpdated = true;
}
break;
case TYPE_PTR:
if ((this.getSubtype().length() == 0) && (rec.getSubtype().length() != 0)) {
_subtype = rec.getSubtype();
serviceUpdated = true;
}
break;
default:
break;
}
if (serviceUpdated && this.hasData()) {
JmDNSImpl dns = this.getDns();
if (dns != null) {
ServiceEvent event = ((DNSRecord) rec).getServiceEvent(dns);
event = new ServiceEventImpl(dns, event.getType(), event.getName(), this);
dns.handleServiceResolved(event);
}
}
// This is done, to notify the wait loop in method JmDNS.waitForInfoData(ServiceInfo info, int timeout);
synchronized (this) {
this.notifyAll();
}
}
}
use of javax.jmdns.ServiceEvent in project JAirPort by froks.
the class JmDNSImpl method registerServiceType.
/**
* {@inheritDoc}
*/
@Override
public boolean registerServiceType(String type) {
boolean typeAdded = false;
Map<Fields, String> map = ServiceInfoImpl.decodeQualifiedNameMapForType(type);
String domain = map.get(Fields.Domain);
String protocol = map.get(Fields.Protocol);
String application = map.get(Fields.Application);
String subtype = map.get(Fields.Subtype);
final String name = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
final String loname = name.toLowerCase();
if (logger.isLoggable(Level.FINE)) {
logger.fine(this.getName() + ".registering service type: " + type + " as: " + name + (subtype.length() > 0 ? " subtype: " + subtype : ""));
}
if (!_serviceTypes.containsKey(loname) && !application.toLowerCase().equals("dns-sd") && !domain.toLowerCase().endsWith("in-addr.arpa") && !domain.toLowerCase().endsWith("ip6.arpa")) {
typeAdded = _serviceTypes.putIfAbsent(loname, new ServiceTypeEntry(name)) == null;
if (typeAdded) {
final ServiceTypeListenerStatus[] list = _typeListeners.toArray(new ServiceTypeListenerStatus[_typeListeners.size()]);
final ServiceEvent event = new ServiceEventImpl(this, name, "", null);
for (final ServiceTypeListenerStatus status : list) {
_executor.submit(new Runnable() {
/** {@inheritDoc} */
@Override
public void run() {
status.serviceTypeAdded(event);
}
});
}
}
}
if (subtype.length() > 0) {
ServiceTypeEntry subtypes = _serviceTypes.get(loname);
if ((subtypes != null) && (!subtypes.contains(subtype))) {
synchronized (subtypes) {
if (!subtypes.contains(subtype)) {
typeAdded = true;
subtypes.add(subtype);
final ServiceTypeListenerStatus[] list = _typeListeners.toArray(new ServiceTypeListenerStatus[_typeListeners.size()]);
final ServiceEvent event = new ServiceEventImpl(this, "_" + subtype + "._sub." + name, "", null);
for (final ServiceTypeListenerStatus status : list) {
_executor.submit(new Runnable() {
/** {@inheritDoc} */
@Override
public void run() {
status.subTypeForServiceTypeAdded(event);
}
});
}
}
}
}
}
return typeAdded;
}
use of javax.jmdns.ServiceEvent in project JAirPort by froks.
the class JmDNSImpl method updateRecord.
// Remind: Method updateRecord should receive a better name.
/**
* Notify all listeners that a record was updated.
*
* @param now
* update date
* @param rec
* DNS record
* @param operation
* DNS cache operation
*/
public void updateRecord(long now, DNSRecord rec, Operation operation) {
// We do not want to block the entire DNS while we are updating the record for each listener (service info)
{
List<DNSListener> listenerList = null;
synchronized (_listeners) {
listenerList = new ArrayList<DNSListener>(_listeners);
}
for (DNSListener listener : listenerList) {
listener.updateRecord(this.getCache(), now, rec);
}
}
if (DNSRecordType.TYPE_PTR.equals(rec.getRecordType())) // if (DNSRecordType.TYPE_PTR.equals(rec.getRecordType()) || DNSRecordType.TYPE_SRV.equals(rec.getRecordType()))
{
ServiceEvent event = rec.getServiceEvent(this);
if ((event.getInfo() == null) || !event.getInfo().hasData()) {
// We do not care about the subtype because the info is only used if complete and the subtype will then be included.
ServiceInfo info = this.getServiceInfoFromCache(event.getType(), event.getName(), "", false);
if (info.hasData()) {
event = new ServiceEventImpl(this, event.getType(), event.getName(), info);
}
}
List<ServiceListenerStatus> list = _serviceListeners.get(event.getType().toLowerCase());
final List<ServiceListenerStatus> serviceListenerList;
if (list != null) {
synchronized (list) {
serviceListenerList = new ArrayList<ServiceListenerStatus>(list);
}
} else {
serviceListenerList = Collections.emptyList();
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".updating record for event: " + event + " list " + serviceListenerList + " operation: " + operation);
}
if (!serviceListenerList.isEmpty()) {
final ServiceEvent localEvent = event;
switch(operation) {
case Add:
for (final ServiceListenerStatus listener : serviceListenerList) {
if (listener.isSynchronous()) {
listener.serviceAdded(localEvent);
} else {
_executor.submit(new Runnable() {
/** {@inheritDoc} */
@Override
public void run() {
listener.serviceAdded(localEvent);
}
});
}
}
break;
case Remove:
for (final ServiceListenerStatus listener : serviceListenerList) {
if (listener.isSynchronous()) {
listener.serviceRemoved(localEvent);
} else {
_executor.submit(new Runnable() {
/** {@inheritDoc} */
@Override
public void run() {
listener.serviceRemoved(localEvent);
}
});
}
}
break;
default:
break;
}
}
}
}
use of javax.jmdns.ServiceEvent in project JAirPort by froks.
the class JmDNSImpl method addServiceListener.
private void addServiceListener(String type, ServiceListener listener, boolean synch) {
ServiceListenerStatus status = new ServiceListenerStatus(listener, synch);
final String loType = type.toLowerCase();
List<ServiceListenerStatus> list = _serviceListeners.get(loType);
if (list == null) {
if (_serviceListeners.putIfAbsent(loType, new LinkedList<ServiceListenerStatus>()) == null) {
if (_serviceCollectors.putIfAbsent(loType, new ServiceCollector(type)) == null) {
// We have a problem here. The service collectors must be called synchronously so that their cache get cleaned up immediately or we will report .
this.addServiceListener(loType, _serviceCollectors.get(loType), ListenerStatus.SYNCHONEOUS);
}
}
list = _serviceListeners.get(loType);
}
if (list != null) {
synchronized (list) {
if (!list.contains(listener)) {
list.add(status);
}
}
}
// report cached service types
final List<ServiceEvent> serviceEvents = new ArrayList<ServiceEvent>();
Collection<DNSEntry> dnsEntryLits = this.getCache().allValues();
for (DNSEntry entry : dnsEntryLits) {
final DNSRecord record = (DNSRecord) entry;
if (record.getRecordType() == DNSRecordType.TYPE_SRV) {
if (record.getKey().endsWith(loType)) {
// Do not used the record embedded method for generating event this will not work.
// serviceEvents.add(record.getServiceEvent(this));
serviceEvents.add(new ServiceEventImpl(this, record.getType(), toUnqualifiedName(record.getType(), record.getName()), record.getServiceInfo()));
}
}
}
// Actually call listener with all service events added above
for (ServiceEvent serviceEvent : serviceEvents) {
status.serviceAdded(serviceEvent);
}
// Create/start ServiceResolver
this.startServiceResolver(type);
}
Aggregations