CanonicalID parentCID = null;
boolean authResComplete = false;
ResolverFlags currentFlags = null; // this is only for overriding by HttpsBypassAuthority settings
String parentXRI = ((XRIAuthority)qxri.getAuthorityPath()).getRootAuthority();
XRISegment remainingSegment = segment;
// if caching in use, we know that the root is always considered "cached"
boolean parentIsCached = cache != null;
while (remainingSegment != null && remainingSegment.getNumSubSegments() > 0) {
// clone flags
currentFlags = new ResolverFlags(flags);
// more subsegments to resolve
String query = remainingSegment.getSubSegmentAt(0).toURINormalForm(true);
log.debug("resolveAuthSegment - resolving subsegment '" + query + "'");
checkMaxRequests(xrdsOut, query, state);
// if HTTPS is requested and what we are resolving is allowed to bypass HTTPS, we turn off the HTTPS flag
// for auth-res service selection
if (currentFlags.isHttps() && isHttpsBypassAuthority(parentXRI)) {
log.debug("Bypassing HTTPS for " + parentXRI);
currentFlags.setHttps(false);
}
//// perform service selection
String authResMediaType = Tags.CONTENT_TYPE_XRDS + ";" + currentFlags.getTrustParameters();
List authResServices = selectServices(parent.getServices(), Tags.SERVICE_AUTH_RES, null, authResMediaType, currentFlags);
if (authResServices.size() < 1) {
log.debug("resolveAuthSegment - no authority resolution service found!");
throw makeResolutionException(
xrdsOut,
query,
Status.AUTH_RES_NOT_FOUND,
"Authority Resolution Service Not Found"
);
}
if (parentIsCached) {
// try retrieving from cache
String xriAuthority = XRI.fromURINormalForm(parentXRI + query).toURINormalForm();
log.debug("resolveAuthSegment - looking up in cache '" + xriAuthority + "'");
byte[] res = cache.get(xriAuthority, currentFlags.isHttps(), currentFlags.isSaml());
log.debug("resolveAuthSegment - cache " + ((res == null)? "MISS" : "HIT"));
if (res != null) {
// cache hit!
XRDS xrdsCached = null;
try {
xrdsCached = readXRDS(new ByteArrayInputStream(res));
}
catch (XRIResolutionException e) {
throw makeResolutionException(
xrdsOut,
query,
Status.INVALID_XRDS,
"Cached XRDS is invalid"
);
}
// we need to pass a Service object representing the authority resolution service
// that was selected but this only matters for SAML resolution, in which case, only
// one is allowed, so we just pass the first Service to it.
Service authRes = (Service) authResServices.get(0);
parseFetchedXRD(xrdsCached, xrdsCached.getDescriptorAt(0), parent, remainingSegment.getSubSegmentAt(0), authRes, flags);
tmpXRDS = xrdsCached;
}
}
// fetch from network if it is not cached
if (tmpXRDS == null) {
// from this subsegment on, no more caching
parentIsCached = false;
try {
// retrieve XRDS documents for the given subsegment
log.trace("resolveAuthSegment - fetching XRDS");
tmpXRDS = fetchAuthXRDS(qxri, parent, authResServices, remainingSegment, currentFlags, state, parentXRI);
}
catch (PartialResolutionException e) {
log.trace("got PRE: " + e.getPartialXRDS());
log.trace("xrdsOut.n = " + xrdsOut.getNumChildren() + ", partialXRDS.n=" + e.getPartialXRDS().getNumChildren());
xrdsOut.addAll(e.getPartialXRDS());
throw new PartialResolutionException(xrdsOut);
}
}
//// add the subsegments
xrdsOut.addAll(tmpXRDS);
//// replace parent XRD
parent = tmpXRDS.getFinalXRD();
for (int k = 0; k < tmpXRDS.getNumChildren(); k++) {
XRISubSegment subseg = remainingSegment.getSubSegmentAt(k);
parentXRI = parentXRI + subseg;
}
remainingSegment = remainingSegment.getRemainder(tmpXRDS.getNumChildren());
tmpXRDS = null;
try {
if (parent.getNumRedirects() > 0) {
log.debug("resolveAuthSegment - processing Redirect(s)");