String identifyingString = thisConnection.getDescription();
if (identifyingString == null || identifyingString.length() == 0)
identifyingString = thisConnection.getName();
// Create a request
AuthRequest ar = new AuthRequest(thisConnection,identifyingString);
authRequests.put(thisConnection.getName(), ar);
// We create an auth thread if there are prerequisites to meet.
// Otherwise, we just fire off the request
String domainUserID = domainMap.get(authDomain);
if (thisConnection.getPrerequisiteMapping() == null)
{
ar.setUserID(domainUserID);
queue.addRequest(ar);
}
else
{
MapperDescription md = new MapperDescription(thisConnection.getPrerequisiteMapping(),authDomain);
AuthOrderThread thread = new AuthOrderThread(identifyingString,
ar, md,
queue, mappingRequests);
authThreads.add(thread);
// The same mapper can be used for multiple domains, although this is likely to be uncommon. Nevertheless,
// mapper invocations need to be segregated to prevent trouble
activeConnections.add(md);
}
}
}
// Create mapping requests
while (!activeConnections.isEmpty())
{
Iterator<MapperDescription> connectionIter = activeConnections.iterator();
MapperDescription mapperDesc = connectionIter.next();
String connectionName = mapperDesc.mapperName;
String authDomain = mapperDesc.authDomain;
IMappingConnection thisConnection = mappingConnMap.get(connectionName);
String identifyingString = thisConnection.getDescription();
if (identifyingString == null || identifyingString.length() == 0)
identifyingString = connectionName;
// Create a request
MappingRequest mr = new MappingRequest(thisConnection,identifyingString);
mappingRequests.put(mapperDesc, mr);
// Either start up a thread, or just fire it off immediately.
if (thisConnection.getPrerequisiteMapping() == null)
{
mr.setUserID(domainMap.get(authDomain));
mappingQueue.addRequest(mr);
}
else
{
//System.out.println("Mapper: prerequisite found: '"+thisConnection.getPrerequisiteMapping()+"'");
MapperDescription p = new MapperDescription(thisConnection.getPrerequisiteMapping(),authDomain);
MappingOrderThread thread = new MappingOrderThread(identifyingString,
mr, p, mappingQueue, mappingRequests);
mappingThreads.add(thread);
if (mappingRequests.get(p) == null)
activeConnections.add(p);
}
activeConnections.remove(mapperDesc);
}
// Start threads. We have to wait until all the requests have been
// at least created before we do this.
for (MappingOrderThread thread : mappingThreads)
{
thread.start();
}
for (AuthOrderThread thread : authThreads)
{
thread.start();
}
// Wait for the threads to finish up. This will guarantee that all entities have run to completion.
for (MappingOrderThread thread : mappingThreads)
{
thread.finishUp();
}
for (AuthOrderThread thread : authThreads)
{
thread.finishUp();
}
// This is probably unnecessary, but we do it anyway just to adhere to the contract
for (MappingRequest mr : mappingRequests.values())
{
mr.waitForComplete();
}
// Handle all exceptions thrown during mapping. In general this just means logging them, because
// the downstream authorities will presumably not find what they are looking for and error out that way.
for (MappingRequest mr : mappingRequests.values())
{
Throwable exception = mr.getAnswerException();
if (exception != null)
{
Logging.authorityService.warn("Mapping exception logged from "+mr.getIdentifyingString()+": "+exception.getMessage()+"; mapper aborted", exception);
}
}
// Now, work through the returning answers.
// Ask all the interrogated authorities for their ACLs, and merge the final list together.
StringBuilder sb = new StringBuilder();
// Set response mime type
response.setContentType("text/plain; charset=ISO8859-1");
ServletOutputStream out = response.getOutputStream();
try
{
for (String connectionName : authRequests.keySet())
{
AuthRequest ar = authRequests.get(connectionName);
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug("Waiting for answer from authority connection "+ar.getIdentifyingString()+" for user '"+ar.getUserID()+"'");
ar.waitForComplete();
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug("Received answer from authority connection "+ar.getIdentifyingString()+" for user '"+ar.getUserID()+"'");
Throwable exception = ar.getAnswerException();
AuthorizationResponse reply = ar.getAnswerResponse();
if (exception != null)
{
// Exceptions are always bad now
// The ManifoldCFException here must disable access to the UI without causing a generic badness thing to happen, so use 403.
if (exception instanceof ManifoldCFException)
response.sendError(response.SC_FORBIDDEN,"From "+ar.getIdentifyingString()+": "+exception.getMessage());
else
response.sendError(response.SC_INTERNAL_SERVER_ERROR,"From "+ar.getIdentifyingString()+": "+exception.getMessage());
return;
}
String authGroup = ar.getAuthorityConnection().getAuthGroup();
// A null reply means the same as USERNOTFOUND; it occurs because a user mapping failed somewhere.
if (reply == null)
{
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug("User '"+ar.getUserID()+"' mapping failed for authority '"+ar.getIdentifyingString()+"'");
sb.append(USERNOTFOUND_VALUE).append(java.net.URLEncoder.encode(ar.getIdentifyingString(),"UTF-8")).append("\n");
}
else if (reply.getResponseStatus() == AuthorizationResponse.RESPONSE_UNREACHABLE)
{
Logging.authorityService.warn("Authority '"+ar.getIdentifyingString()+"' is unreachable for user '"+ar.getUserID()+"'");
sb.append(UNREACHABLE_VALUE).append(java.net.URLEncoder.encode(ar.getIdentifyingString(),"UTF-8")).append("\n");
}
else if (reply.getResponseStatus() == AuthorizationResponse.RESPONSE_USERUNAUTHORIZED)
{
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug("Authority '"+ar.getIdentifyingString()+"' does not authorize user '"+ar.getUserID()+"'");
sb.append(UNAUTHORIZED_VALUE).append(java.net.URLEncoder.encode(ar.getIdentifyingString(),"UTF-8")).append("\n");
}
else if (reply.getResponseStatus() == AuthorizationResponse.RESPONSE_USERNOTFOUND)
{
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug("User '"+ar.getUserID()+"' unknown to authority '"+ar.getIdentifyingString()+"'");
sb.append(USERNOTFOUND_VALUE).append(java.net.URLEncoder.encode(ar.getIdentifyingString(),"UTF-8")).append("\n");
}
else
sb.append(AUTHORIZED_VALUE).append(java.net.URLEncoder.encode(ar.getIdentifyingString(),"UTF-8")).append("\n");
String[] acl = reply.getAccessTokens();
if (acl != null)
{
if (aclneeded)
{
int j = 0;
while (j < acl.length)
{
if (Logging.authorityService.isDebugEnabled())
Logging.authorityService.debug(" User '"+ar.getUserID()+"' has Acl = '"+acl[j]+"' from authority '"+ar.getIdentifyingString()+"'");
sb.append(TOKEN_PREFIX).append(java.net.URLEncoder.encode(authGroup,"UTF-8")).append(":").append(java.net.URLEncoder.encode(acl[j++],"UTF-8")).append("\n");
}
}
}
}