Author: kwright
Date: Wed Oct 23 12:45:31 2013
New Revision: 1535006
URL: http://svn.apache.org/r1535006
Log:
Flesh out multi-domain requests to authority service
Modified:
manifoldcf/branches/CONNECTORS-792/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authority/AuthorityConnectionManager.java
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectionManager.java
Modified:
manifoldcf/branches/CONNECTORS-792/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
URL:
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-792/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java?rev=1535006&r1=1535005&r2=1535006&view=diff
==============================================================================
---
manifoldcf/branches/CONNECTORS-792/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
(original)
+++
manifoldcf/branches/CONNECTORS-792/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
Wed Oct 23 12:45:31 2013
@@ -106,13 +106,37 @@ public class UserACLServlet extends Http
Logging.authorityService.debug("Received request");
+ Map<String,String> domainMap = new HashMap<String,String>();
+
+ // Legacy mode: single user name with optional domain
String userID = request.getParameter("username");
- if (userID == null)
+ if (userID != null)
+ {
+ String domain = request.getParameter("domain");
+ if (domain == null)
+ domain = "";
+ domainMap.put(domain,userID);
+ }
+
+ // Now, go through enumerated username/domain pairs
+ int q = 0;
+ while (true)
+ {
+ String enumUserName = request.getParameter("username_"+q);
+ if (enumUserName == null)
+ break;
+ String enumDomain = request.getParameter("domain_"+q);
+ if (enumDomain == null)
+ enumDomain = "";
+ domainMap.put(enumDomain,enumUserName);
+ }
+
+ if (domainMap.size() == 0)
{
response.sendError(response.SC_BAD_REQUEST);
return;
}
-
+
boolean idneeded = false;
boolean aclneeded = true;
@@ -135,7 +159,18 @@ public class UserACLServlet extends Http
if (Logging.authorityService.isDebugEnabled())
{
- Logging.authorityService.debug("Received authority request for user
'"+userID+"'");
+ StringBuilder sb2 = new StringBuilder("[");
+ boolean first = true;
+ for (String domain : domainMap.keySet())
+ {
+ if (first)
+ first = false;
+ else
+ sb2.append(",");
+
sb2.append("'").append(domain).append("':'").append(domainMap.get(domain)).append("'");
+ }
+ sb2.append("]");
+ Logging.authorityService.debug("Received authority request for
domain:user set "+sb2.toString());
}
RequestQueue<MappingRequest> mappingQueue =
ManifoldCF.getMappingRequestQueue();
@@ -158,15 +193,15 @@ public class UserACLServlet extends Http
IMappingConnectionManager mappingConnManager =
MappingConnectionManagerFactory.make(itc);
IAuthorityConnectionManager authConnManager =
AuthorityConnectionManagerFactory.make(itc);
+ // Get all mapping connections; we may not need them all but we do need
to be able to look them all up
IMappingConnection[] mappingConnections =
mappingConnManager.getAllConnections();
- IAuthorityConnection[] connections = authConnManager.getAllConnections();
// One thread per connection, which is responsible for starting the
mapping process when it is ready.
List<MappingOrderThread> mappingThreads = new
ArrayList<MappingOrderThread>();
// One thread per authority, which is responsible for starting the auth
request when it is ready.
List<AuthOrderThread> authThreads = new ArrayList<AuthOrderThread>();
- Map<String,MappingRequest> mappingRequests = new
HashMap<String,MappingRequest>();
+ Map<MapperDescription,MappingRequest> mappingRequests = new
HashMap<MapperDescription,MappingRequest>();
Map<String,AuthRequest> authRequests = new HashMap<String,AuthRequest>();
Map<String,IMappingConnection> mappingConnMap = new
HashMap<String,IMappingConnection>();
@@ -178,46 +213,56 @@ public class UserACLServlet extends Http
}
// Set of connections we need to fire off
- Set<String> activeConnections = new HashSet<String>();
+ Set<MapperDescription> activeConnections = new
HashSet<MapperDescription>();
// We do the minimal set of mapping requests and authorities. Since it
is the authority tokens we are
// looking for, we start there, and build authority requests first, then
mapping requests that support them,
// etc.
// Create auth requests
- for (int i = 0; i < connections.length; i++)
+ for (String authDomain : domainMap.keySet())
{
- IAuthorityConnection thisConnection = connections[i];
- String identifyingString = thisConnection.getDescription();
- if (identifyingString == null || identifyingString.length() == 0)
- identifyingString = thisConnection.getName();
-
- // Create a request
- AuthRequest ar = new AuthRequest(
-
thisConnection.getClassName(),identifyingString,thisConnection.getConfigParams(),thisConnection.getMaxConnections());
- authRequests.put(thisConnection.getName(), ar);
-
- // We create an auth thread if there are prerequisites to meet.
- // Otherwise, we just fire off the request
- if (thisConnection.getPrerequisiteMapping() == null)
- {
- ar.setUserID(userID);
- queue.addRequest(ar);
- }
- else
+ IAuthorityConnection[] connections =
authConnManager.getDomainConnections(authDomain);
+ for (int i = 0; i < connections.length; i++)
{
- AuthOrderThread thread = new AuthOrderThread(identifyingString,
- ar, thisConnection.getPrerequisiteMapping(),
- queue, mappingRequests);
- authThreads.add(thread);
- activeConnections.add(thisConnection.getPrerequisiteMapping());
+ IAuthorityConnection thisConnection = connections[i];
+ String identifyingString = thisConnection.getDescription();
+ if (identifyingString == null || identifyingString.length() == 0)
+ identifyingString = thisConnection.getName();
+
+ // Create a request
+ AuthRequest ar = new AuthRequest(
+
thisConnection.getClassName(),identifyingString,thisConnection.getConfigParams(),thisConnection.getMaxConnections());
+ 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<String> connectionIter = activeConnections.iterator();
- String connectionName = connectionIter.next();
+ 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)
@@ -226,25 +271,25 @@ public class UserACLServlet extends Http
// Create a request
MappingRequest mr = new MappingRequest(
thisConnection.getClassName(),identifyingString,thisConnection.getConfigParams(),thisConnection.getMaxConnections());
- mappingRequests.put(connectionName, mr);
+ mappingRequests.put(mapperDesc, mr);
// Either start up a thread, or just fire it off immediately.
if (thisConnection.getPrerequisiteMapping() == null)
{
- mr.setUserID(userID);
+ 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, thisConnection.getPrerequisiteMapping(), mappingQueue,
mappingRequests);
+ mr, p, mappingQueue, mappingRequests);
mappingThreads.add(thread);
- String p = thisConnection.getPrerequisiteMapping();
if (mappingRequests.get(p) == null)
activeConnections.add(p);
}
- activeConnections.remove(connectionName);
+ activeConnections.remove(mapperDesc);
}
// Start threads. We have to wait until all the requests have been
@@ -287,25 +332,24 @@ public class UserACLServlet extends Http
// Now, work through the returning answers.
- // Ask all the registered authorities for their ACLs, and merge the
final list together.
+ // 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 (int i = 0; i < connections.length; i++)
+ for (String connectionName : authRequests.keySet())
{
- IAuthorityConnection ac = connections[i];
- AuthRequest ar = authRequests.get(ac.getName());
+ AuthRequest ar = authRequests.get(connectionName);
if (Logging.authorityService.isDebugEnabled())
- Logging.authorityService.debug("Waiting for answer from connector
class '"+ac.getClassName()+"' for user '"+userID+"'");
+ 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 connector
class '"+ac.getClassName()+"' for user '"+userID+"'");
+ Logging.authorityService.debug("Received answer from authority
connection "+ar.getIdentifyingString()+" for user '"+ar.getUserID()+"'");
Throwable exception = ar.getAnswerException();
AuthorizationResponse reply = ar.getAnswerResponse();
@@ -324,24 +368,24 @@ public class UserACLServlet extends Http
if (reply == null)
{
if (Logging.authorityService.isDebugEnabled())
- Logging.authorityService.debug("User '"+userID+"' mapping failed
for authority '"+ar.getIdentifyingString()+"'");
+ 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 '"+userID+"'");
+ 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 '"+userID+"'");
+ 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 '"+userID+"' unknown to
authority '"+ar.getIdentifyingString()+"'");
+ 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
@@ -356,14 +400,15 @@ public class UserACLServlet extends Http
while (j < acl.length)
{
if (Logging.authorityService.isDebugEnabled())
- Logging.authorityService.debug(" User '"+userID+"' has Acl
= '"+acl[j]+"' from authority '"+ar.getIdentifyingString()+"'");
-
sb.append(TOKEN_PREFIX).append(java.net.URLEncoder.encode(ac.getName(),"UTF-8")).append(":").append(java.net.URLEncoder.encode(acl[j++],"UTF-8")).append("\n");
+ Logging.authorityService.debug(" User '"+ar.getUserID()+"'
has Acl = '"+acl[j]+"' from authority '"+ar.getIdentifyingString()+"'");
+
sb.append(TOKEN_PREFIX).append(java.net.URLEncoder.encode(connectionName,"UTF-8")).append(":").append(java.net.URLEncoder.encode(acl[j++],"UTF-8")).append("\n");
}
}
}
}
- if (idneeded)
+ // Maintained for backwards compatibility only; no practical use that
I can determine here
+ if (idneeded && userID != null)
sb.append(ID_PREFIX).append(java.net.URLEncoder.encode(userID,"UTF-8")).append("\n");
byte[] responseValue = sb.toString().getBytes("ISO8859-1");
@@ -378,7 +423,20 @@ public class UserACLServlet extends Http
}
if (Logging.authorityService.isDebugEnabled())
- Logging.authorityService.debug("Done with request for '"+userID+"'");
+ {
+ StringBuilder sb2 = new StringBuilder("[");
+ boolean first = true;
+ for (String domain : domainMap.keySet())
+ {
+ if (first)
+ first = false;
+ else
+ sb2.append(",");
+
sb2.append("'").append(domain).append("':'").append(domainMap.get(domain)).append("'");
+ }
+ sb2.append("]");
+ Logging.authorityService.debug("Done with request for domain:user set
"+sb2.toString());
+ }
}
catch (InterruptedException e)
{
@@ -396,6 +454,34 @@ public class UserACLServlet extends Http
}
}
+ /** This class represents a tuple of (mapper_name, auth_domain).
+ */
+ protected static class MapperDescription
+ {
+ public final String mapperName;
+ public final String authDomain;
+
+ public MapperDescription(String mapperName, String authDomain)
+ {
+ this.mapperName = mapperName;
+ this.authDomain = authDomain;
+ }
+
+ public int hashCode()
+ {
+ return mapperName.hashCode() + authDomain.hashCode();
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof MapperDescription))
+ return false;
+ MapperDescription other = (MapperDescription)o;
+ return this.mapperName.equals(other.mapperName) &&
+ this.authDomain.equals(other.authDomain);
+ }
+ }
+
/** This thread is responsible for making sure that the constraints for a
given mapping connection
* are met, and then when they are, firing off a MappingRequest. One of
these threads is spun up
* for every IMappingConnection being handled.
@@ -406,8 +492,8 @@ public class UserACLServlet extends Http
protected static class MappingOrderThread extends Thread
{
protected final MappingRequest request;
- protected final String prerequisite;
- protected final Map<String,MappingRequest> requests;
+ protected final MapperDescription prerequisite;
+ protected final Map<MapperDescription,MappingRequest> requests;
protected final RequestQueue<MappingRequest> mappingRequestQueue;
protected Throwable exception = null;
@@ -415,9 +501,9 @@ public class UserACLServlet extends Http
public MappingOrderThread(
String identifyingString,
MappingRequest request,
- String prerequisite,
+ MapperDescription prerequisite,
RequestQueue<MappingRequest> mappingRequestQueue,
- Map<String, MappingRequest> requests)
+ Map<MapperDescription, MappingRequest> requests)
{
super();
this.request = request;
@@ -469,8 +555,8 @@ public class UserACLServlet extends Http
protected static class AuthOrderThread extends Thread
{
protected final AuthRequest request;
- protected final String prerequisite;
- protected final Map<String,MappingRequest> mappingRequests;
+ protected final MapperDescription prerequisite;
+ protected final Map<MapperDescription,MappingRequest> mappingRequests;
protected final RequestQueue<AuthRequest> authRequestQueue;
protected Throwable exception = null;
@@ -478,9 +564,9 @@ public class UserACLServlet extends Http
public AuthOrderThread(
String identifyingString,
AuthRequest request,
- String prerequisite,
+ MapperDescription prerequisite,
RequestQueue<AuthRequest> authRequestQueue,
- Map<String, MappingRequest> mappingRequests)
+ Map<MapperDescription, MappingRequest> mappingRequests)
{
super();
this.request = request;
Modified:
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authority/AuthorityConnectionManager.java
URL:
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authority/AuthorityConnectionManager.java?rev=1535006&r1=1535005&r2=1535006&view=diff
==============================================================================
---
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authority/AuthorityConnectionManager.java
(original)
+++
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/authority/AuthorityConnectionManager.java
Wed Oct 23 12:45:31 2013
@@ -213,7 +213,53 @@ public class AuthorityConnectionManager
}
}
- /** Obtain a list of the repository connections, ordered by name.
+ /** Obtain a list of the authority connections which correspond to an auth
domain.
+ *@param authDomain is the domain to get connections for.
+ *@return an array of connection objects.
+ */
+ @Override
+ public IAuthorityConnection[] getDomainConnections(String authDomain)
+ throws ManifoldCFException
+ {
+ beginTransaction();
+ try
+ {
+ // Read the connections for the domain
+ StringSetBuffer ssb = new StringSetBuffer();
+ ssb.add(getAuthorityConnectionsKey());
+ StringSet localCacheKeys = new StringSet(ssb);
+ StringBuilder sb = new StringBuilder("SELECT ");
+ ArrayList list = new ArrayList();
+ sb.append(nameField).append(" FROM ").append(getTableName()).append("
WHERE ");
+ sb.append(buildConjunctionClause(list,new ClauseDescription[]{new
UnitaryClause(authDomainField,authDomain)}));
+ IResultSet set = performQuery(sb.toString(),list,localCacheKeys,null);
+ String[] names = new String[set.getRowCount()];
+ int i = 0;
+ while (i < names.length)
+ {
+ IResultRow row = set.getRow(i);
+ names[i] = row.getValue(nameField).toString();
+ i++;
+ }
+ return loadMultiple(names);
+ }
+ catch (ManifoldCFException e)
+ {
+ signalRollback();
+ throw e;
+ }
+ catch (Error e)
+ {
+ signalRollback();
+ throw e;
+ }
+ finally
+ {
+ endTransaction();
+ }
+ }
+
+ /** Obtain a list of the authority connections, ordered by name.
*@return an array of connection objects.
*/
@Override
Modified:
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectionManager.java
URL:
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectionManager.java?rev=1535006&r1=1535005&r2=1535006&view=diff
==============================================================================
---
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectionManager.java
(original)
+++
manifoldcf/branches/CONNECTORS-792/framework/pull-agent/src/main/java/org/apache/manifoldcf/authorities/interfaces/IAuthorityConnectionManager.java
Wed Oct 23 12:45:31 2013
@@ -51,6 +51,13 @@ public interface IAuthorityConnectionMan
public IAuthorityConnection[] getAllConnections()
throws ManifoldCFException;
+ /** Obtain a list of the authority connections which correspond to an auth
domain.
+ *@param authDomain is the domain to get connections for.
+ *@return an array of connection objects.
+ */
+ public IAuthorityConnection[] getDomainConnections(String authDomain)
+ throws ManifoldCFException;
+
/** Load a authority connection by name.
*@param name is the name of the authority connection.
*@return the loaded connection object, or null if not found.