microsoft.exchange.webservices.data.AutodiscoverDnsClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of exchange-ws-api Show documentation
Show all versions of exchange-ws-api Show documentation
The source came from http://archive.msdn.microsoft.com/ewsjavaapi
Support for Maven has been added.
The newest version!
/**************************************************************************
* copyright file="AutodiscoverDnsClient.java" company="Microsoft"
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Defines the AutodiscoverDnsClient.java.
**************************************************************************/
package microsoft.exchange.webservices.data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.xml.stream.XMLStreamException;
/**
* Class that reads AutoDiscover configuration information from DNS.
*/
class AutodiscoverDnsClient {
/**
* SRV DNS prefix to lookup.
*/
private static final String AutoDiscoverSrvPrefix = "_autodiscover._tcp.";
/**
* We are only interested in records that use SSL.
*/
private static final int SslPort = 443;
/**
* Random selector in the case of ties.
*/
private static Random RandomTieBreakerSelector = new Random();
/**
* AutodiscoverService using this DNS reader.
*/
private AutodiscoverService service;
/**
* Initializes a new instance of the class.
*
* @param service
* the service
*/
protected AutodiscoverDnsClient(AutodiscoverService service) {
this.service = service;
}
/**
* Finds the Autodiscover host from DNS SRV records.
*
* @param domain
* the domain
* @return Autodiscover hostname (will be null if lookup failed).
* @throws XMLStreamException
* the xML stream exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
protected String findAutodiscoverHostFromSrv(String domain)
throws XMLStreamException, IOException {
String domainToMatch = AutoDiscoverSrvPrefix + domain;
DnsSrvRecord dnsSrvRecord = this
.findBestMatchingSrvRecord(domainToMatch);
if ((dnsSrvRecord == null) || dnsSrvRecord.getNameTarget() == null ||
dnsSrvRecord.getNameTarget().isEmpty()) {
this.service.traceMessage(TraceFlags.AutodiscoverConfiguration,
"No appropriate SRV record was found.");
return null;
} else {
this.service.traceMessage(TraceFlags.AutodiscoverConfiguration,
String.format(
"DNS query for SRV record for domain %s found %s",
domain, dnsSrvRecord.getNameTarget()));
return dnsSrvRecord.getNameTarget();
}
}
/**
* Finds the best matching SRV record.
*
* @param domain
* the domain
* @return DnsSrvRecord(will be null if lookup failed).
* @throws XMLStreamException
* the xML stream exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private DnsSrvRecord findBestMatchingSrvRecord(String domain)
throws XMLStreamException, IOException {
List dnsSrvRecordList;
try {
// Make DnsQuery call to get collection of SRV records.
dnsSrvRecordList = DnsClient.dnsQuery(DnsSrvRecord.class, domain,
this.service.getDnsServerAddress());
} catch (DnsException ex) {
String dnsExcMessage = String.format("DnsQuery returned error " +
"error '%s' error code 0x{1:X8}.",
ex.getMessage(), ex.getError());
this.service
.traceMessage(
TraceFlags.AutodiscoverConfiguration,
dnsExcMessage);
return null;
} catch (SecurityException ex) {
// In restricted environments, we may not be allowed to call
// unmanaged code.
this.service.traceMessage(TraceFlags.AutodiscoverConfiguration,
String.format(
"DnsQuery cannot be called. Security error: %s.",
ex.getMessage()));
return null;
}
this.service.traceMessage(TraceFlags.AutodiscoverConfiguration, String
.format("%d SRV records were returned.", dnsSrvRecordList
.size()));
// If multiple records were returned, they will be returned sorted by
// priority
// (and weight) order. Need to find the index of the first record that
// supports SSL.
int priority = Integer.MIN_VALUE;
int weight = Integer.MAX_VALUE;
boolean recordFound = false;
for (DnsSrvRecord dnsSrvRecord : dnsSrvRecordList) {
if (dnsSrvRecord.getPort() == SslPort) {
priority = dnsSrvRecord.getPriority();
weight = dnsSrvRecord.getWeight();
recordFound = true;
break;
}
}
// Records were returned but nothing matched our criteria.
if (!recordFound) {
this.service.traceMessage(TraceFlags.AutodiscoverConfiguration,
"No appropriate SRV records were found.");
return null;
}
List bestDnsSrvRecordList = new ArrayList();
for (DnsSrvRecord dnsSrvRecord : dnsSrvRecordList) {
if (dnsSrvRecord.getPort() == SslPort &&
dnsSrvRecord.getPriority() == priority &&
dnsSrvRecord.getWeight() == weight) {
bestDnsSrvRecordList.add(dnsSrvRecord);
}
}
// The list must contain at least one matching record since we found one
// earlier.
EwsUtilities.EwsAssert(dnsSrvRecordList.size() > 0,
"AutodiscoverDnsClient.FindBestMatchingSrvRecord",
"At least one DNS SRV record must match the criteria.");
// If we have multiple records with the same priority and weight,
// randomly pick one.
int recordIndex = (bestDnsSrvRecordList.size() > 1) ?
RandomTieBreakerSelector
.nextInt(bestDnsSrvRecordList.size()) :
0;
DnsSrvRecord bestDnsSrvRecord = bestDnsSrvRecordList.get(recordIndex);
String traceMessage = String.format("Returning SRV record %d " +
"of %d records. " +
"Target: %s, Priority: %d, Weight: %d",
recordIndex, dnsSrvRecordList.size(),
bestDnsSrvRecord.getNameTarget(),
bestDnsSrvRecord.getPriority(),
bestDnsSrvRecord.getWeight());
this.service.traceMessage(TraceFlags.
AutodiscoverConfiguration, traceMessage);
return bestDnsSrvRecord;
}
}