*/
public void resolve(ResolverAttribute attribute, Principal principal, String requester, Dependencies depends)
throws ResolutionPlugInException;
-
- /**
- * Returns an array containing the names of the attribute
- * definitions that this definition depends upon for resolution.
- *
- * @return String[] an array of Ids
- */
- public String[] getAttributeDefinitionDependencyIds();
-
- /**
- * Returns an array containining the names of the connectors
- * that this definition depends upon for resolution.
- *
- * @return String[] an array of Ids
- */
- public String[] getDataConnectorDependencyIds();
}
package edu.internet2.middleware.shibboleth.aa.attrresolv;
import java.io.IOException;
-import java.io.InputStream;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
parser.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
if (systemId.endsWith("shibboleth-resolver-1.0.xsd")) {
- InputStream stream;
try {
return new InputSource(
new ShibResource("/schemas/shibboleth-resolver-1.0.xsd", this.getClass())
while (registered.hasNext()) {
ResolutionPlugIn plugIn = lookupPlugIn((String) registered.next());
log.debug("Checking PlugIn (" + plugIn.getId() + ") for consistency.");
- if (plugIn instanceof AttributeDefinitionPlugIn) {
- verifyPlugIn((AttributeDefinitionPlugIn) plugIn, new HashSet(), inconsistent);
- }
+ verifyPlugIn(plugIn, new HashSet(), inconsistent);
}
if (!inconsistent.isEmpty()) {
}
- private void verifyPlugIn(AttributeDefinitionPlugIn plugIn, Set verifyChain, Set inconsistent) {
+ private void verifyPlugIn(ResolutionPlugIn plugIn, Set verifyChain, Set inconsistent) {
//Short-circuit if we have already found this PlugIn to be inconsistent
if (inconsistent.contains(plugIn.getId())) {
return;
}
- //Make sure all dependent Data Connectors are registered
+ //Recursively go through all DataConnector dependencies and make sure all are registered and consistent.
List depends = new ArrayList();
depends.addAll(Arrays.asList(plugIn.getDataConnectorDependencyIds()));
Iterator dependsIt = depends.iterator();
inconsistent.add(plugIn.getId());
return;
}
+
+ verifyChain.add(plugIn.getId());
+ verifyPlugIn(dependent, verifyChain, inconsistent);
+
+ if (inconsistent.contains(key)) {
+ log.error(
+ "The PlugIn ("
+ + plugIn.getId()
+ + ") is inconsistent. It depends on a PlugIn ("
+ + key
+ + ") that is not inconsistent.");
+ inconsistent.add(plugIn.getId());
+ return;
+ }
}
//Recursively go through all AttributeDefinition dependencies and make sure all are registered and consistent.
}
verifyChain.add(plugIn.getId());
- verifyPlugIn((AttributeDefinitionPlugIn) dependent, verifyChain, inconsistent);
+ verifyPlugIn(dependent, verifyChain, inconsistent);
if (inconsistent.contains(key)) {
log.error(
}
return (String[]) found.toArray(new String[0]);
}
+
+ private Attributes resolveConnector(
+ String connector,
+ Principal principal,
+ String requester,
+ Map requestCache,
+ ResolverAttributeSet requestedAttributes)
+ throws ResolutionPlugInException {
+
+ DataConnectorPlugIn currentDefinition = (DataConnectorPlugIn)lookupPlugIn(connector);
+
+ //Check to see if we have already resolved the connector during this request
+ if (requestCache.containsKey(currentDefinition.getId())) {
+ log.debug(
+ "Connector ("
+ + currentDefinition.getId()
+ + ") already resolved for this request, using cached version");
+ return (Attributes)requestCache.get(currentDefinition.getId());
+ }
+
+ //Check to see if we have a cached resolution for this connector
+ if (currentDefinition.getTTL() > 0) {
+ Attributes cachedAttributes =
+ resolverCache.getResolvedConnector(principal, currentDefinition.getId());
+ if (cachedAttributes != null) {
+ log.debug(
+ "Connector ("
+ + currentDefinition.getId()
+ + ") resolution cached from a previous request, using cached version");
+ return cachedAttributes;
+ }
+ }
+
+ //Resolve all attribute dependencies
+ String[] attributeDependencies = currentDefinition.getAttributeDefinitionDependencyIds();
+ Dependencies depends = new Dependencies();
+
+ for (int i = 0; attributeDependencies.length > i; i++) {
+ log.debug(
+ "Connector (" + currentDefinition.getId() + ") depends on attribute (" + attributeDependencies[i] + ").");
+ ResolverAttribute dependant = requestedAttributes.getByName(attributeDependencies[i]);
+ if (dependant == null) {
+ dependant = new DependentOnlyResolutionAttribute(attributeDependencies[i]);
+ }
+ resolveAttribute(dependant, principal, requester, requestCache, requestedAttributes);
+ depends.addAttributeResolution(attributeDependencies[i], dependant);
+
+ }
+
+ //Resolve all connector dependencies
+ String[] connectorDependencies = currentDefinition.getDataConnectorDependencyIds();
+ for (int i = 0; connectorDependencies.length > i; i++) {
+ log.debug(
+ "Connector (" + currentDefinition.getId() + ") depends on connector (" + connectorDependencies[i] + ").");
+ depends.addConnectorResolution(
+ connectorDependencies[i],
+ resolveConnector(connectorDependencies[i], principal, requester, requestCache, requestedAttributes));
+ }
+
+ //Resolve the connector
+ Attributes resolvedAttributes = currentDefinition.resolve(principal, requester, depends);
+
+ //If necessary, cache for this request
+ requestCache.put(currentDefinition.getId(), resolvedAttributes);
+
+ //Add attribute resolution to cache
+ if (currentDefinition.getTTL() > 0) {
+ resolverCache.cacheConnectorResolution(
+ principal,
+ currentDefinition.getId(),
+ currentDefinition.getTTL(),
+ resolvedAttributes);
+ }
+
+ return resolvedAttributes;
+ }
private void resolveAttribute(
ResolverAttribute attribute,
}
//Resolve all attribute dependencies
- String[] attributeDependencies = currentDefinition.getAttributeDefinitionDependencyIds();
Dependencies depends = new Dependencies();
+ String[] attributeDependencies = currentDefinition.getAttributeDefinitionDependencyIds();
boolean dependancyOnly = false;
for (int i = 0; attributeDependencies.length > i; i++) {
for (int i = 0; connectorDependencies.length > i; i++) {
log.debug(
"Attribute (" + attribute.getName() + ") depends on connector (" + connectorDependencies[i] + ").");
- //Check to see if we have already resolved the connector during this request
- if (requestCache.containsKey(connectorDependencies[i])) {
- log.debug(
- "Connector ("
- + connectorDependencies[i]
- + ") already resolved for this request, using cached version");
- depends.addConnectorResolution(
- connectorDependencies[i],
- (Attributes) requestCache.get(connectorDependencies[i]));
- } else {
- //Check to see if we have a cached resolution for this attribute
- if (((DataConnectorPlugIn) lookupPlugIn(connectorDependencies[i])).getTTL() > 0) {
- Attributes cachedAttributes =
- resolverCache.getResolvedConnector(principal, connectorDependencies[i]);
- if (cachedAttributes != null) {
- log.debug(
- "Connector ("
- + connectorDependencies[i]
- + ") resolution cached from a previous request, using cached version");
- depends.addConnectorResolution(connectorDependencies[i], cachedAttributes);
- }
- }
-
- Attributes resolvedConnector =
- ((DataConnectorPlugIn) lookupPlugIn(connectorDependencies[i])).resolve(principal);
- requestCache.put(connectorDependencies[i], resolvedConnector);
- depends.addConnectorResolution(connectorDependencies[i], resolvedConnector);
-
- //Add attribute resolution to cache
- if (((DataConnectorPlugIn) lookupPlugIn(connectorDependencies[i])).getTTL() > 0) {
- resolverCache.cacheConnectorResolution(
- principal,
- connectorDependencies[i],
- ((DataConnectorPlugIn) lookupPlugIn(connectorDependencies[i])).getTTL(),
- resolvedConnector);
- }
- }
+ depends.addConnectorResolution(
+ connectorDependencies[i],
+ resolveConnector(connectorDependencies[i], principal, requester, requestCache, requestedAttributes));
}
//Resolve the attribute
public interface DataConnectorPlugIn extends ResolutionPlugIn {
- public Attributes resolve(Principal principal) throws ResolutionPlugInException;
+ /**
+ * Resolves the values of a data connector.
+ *
+ * @param principal The principal for which the connector should be resolved
+ * @param requester The name of the entity making the resolution request
+ * @param depends Resolution dependencies
+ * @throws ResolutionPlugInException
+ */
+ public Attributes resolve(Principal principal, String requester, Dependencies depends) throws ResolutionPlugInException;
}
public String getId();
public long getTTL();
+ /**
+ * Returns an array containing the names of the attribute
+ * definitions that this definition depends upon for resolution.
+ *
+ * @return String[] an array of Ids
+ */
+ public String[] getAttributeDefinitionDependencyIds();
+
+ /**
+ * Returns an array containining the names of the connectors
+ * that this definition depends upon for resolution.
+ *
+ * @return String[] an array of Ids
+ */
+ public String[] getDataConnectorDependencyIds();
}
package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
-import java.util.HashSet;
-import java.util.Set;
-
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn;
-import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
/**
protected long lifeTime = -1;
private static Logger log = Logger.getLogger(BaseAttributeDefinition.class.getName());
- protected Set connectorDependencyIds = new HashSet();
- protected Set attributeDependencyIds = new HashSet();
protected BaseAttributeDefinition(Element e) throws ResolutionPlugInException {
log.error("Bad value for attribute (lifeTime) for Attribute Definition (" + getId() + ").");
}
}
-
- NodeList connectorNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "DataConnectorDependency");
-
- for (int i = 0; connectorNodes.getLength() > i; i++) {
- Element connector = (Element) connectorNodes.item(i);
- String connectorName = connector.getAttribute("requires");
- if (connectorName != null && !connectorName.equals("")) {
- addDataConnectorDependencyId(connectorName);
- } else {
- log.error("Data Connector dependency must be accomanied by a \"requires\" attribute.");
- throw new ResolutionPlugInException("Failed to initialize Attribute PlugIn.");
- }
- }
-
- NodeList attributeNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "AttributeDependency");
- for (int i = 0; attributeNodes.getLength() > i; i++) {
- Element attribute = (Element) attributeNodes.item(i);
- String attributeName = attribute.getAttribute("requires");
- if (attributeName != null && !attributeName.equals("")) {
- addAttributeDefinitionDependencyId(attributeName);
- } else {
- log.error("Attribute Definition dependency must be accomanied by a \"requires\" attribute.");
- throw new ResolutionPlugInException("Failed to initialize Attribute PlugIn.");
- }
- }
-
- if (connectorNodes.getLength() == 0 && attributeNodes.getLength() == 0) {
- log.debug("Attribute " + getId() + " has no registered dependencies.");
- }
-
- }
-
- protected void addDataConnectorDependencyId(String id) {
- connectorDependencyIds.add(id);
- }
-
- protected void addAttributeDefinitionDependencyId(String id) {
- attributeDependencyIds.add(id);
}
-
- /**
- * @see edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn#getAttributeDependencyIds()
- */
- public String[] getAttributeDefinitionDependencyIds() {
- return (String[]) attributeDependencyIds.toArray(new String[0]);
- }
-
- /**
- * @see edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn#getConnectorDependencyIds()
- */
- public String[] getDataConnectorDependencyIds() {
- return (String[]) connectorDependencyIds.toArray(new String[0]);
- }
-
}
package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
+import java.util.HashSet;
+import java.util.Set;
+
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
/**
/** Time, in seconds, for which the Attribute Resolver should cache resolutions of this PlugIn. */
protected long ttl = 0;
+ /** Dependencies. */
+ protected Set connectorDependencyIds = new HashSet();
+ protected Set attributeDependencyIds = new HashSet();
+
protected BaseResolutionPlugIn(Element e) throws ResolutionPlugInException {
String id = e.getAttribute("id");
if (id == null || id.equals("")) {
throw new ResolutionPlugInException("Failed to initialize Resolution PlugIn.");
}
}
+
+ NodeList connectorNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "DataConnectorDependency");
+
+ for (int i = 0; connectorNodes.getLength() > i; i++) {
+ Element connector = (Element) connectorNodes.item(i);
+ String connectorName = connector.getAttribute("requires");
+ if (connectorName != null && !connectorName.equals("")) {
+ addDataConnectorDependencyId(connectorName);
+ } else {
+ log.error("Data Connector dependency must be accompanied by a \"requires\" attribute.");
+ throw new ResolutionPlugInException("Failed to initialize Resolution PlugIn.");
+ }
+ }
+
+ NodeList attributeNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "AttributeDependency");
+ for (int i = 0; attributeNodes.getLength() > i; i++) {
+ Element attribute = (Element) attributeNodes.item(i);
+ String attributeName = attribute.getAttribute("requires");
+ if (attributeName != null && !attributeName.equals("")) {
+ addAttributeDefinitionDependencyId(attributeName);
+ } else {
+ log.error("Attribute Definition dependency must be accompanied by a \"requires\" attribute.");
+ throw new ResolutionPlugInException("Failed to initialize Resolution PlugIn.");
+ }
+ }
}
/** Returns the identifier for this PlugIn. */
return ttl;
}
+ protected void addDataConnectorDependencyId(String id) {
+ connectorDependencyIds.add(id);
+ }
+
+ protected void addAttributeDefinitionDependencyId(String id) {
+ attributeDependencyIds.add(id);
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugIn#getAttributeDependencyIds()
+ */
+ public String[] getAttributeDefinitionDependencyIds() {
+ return (String[]) attributeDependencyIds.toArray(new String[0]);
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugIn#getConnectorDependencyIds()
+ */
+ public String[] getDataConnectorDependencyIds() {
+ return (String[]) connectorDependencyIds.toArray(new String[0]);
+ }
}
public String[] getDataConnectorDependencyIds() {
return custom.getDataConnectorDependencyIds();
}
-
}
import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
/**
/**
* @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#resolve(Principal)
*/
- public Attributes resolve(Principal principal) throws ResolutionPlugInException {
- return custom.resolve(principal);
+ public Attributes resolve(Principal principal, String requester, Dependencies depends) throws ResolutionPlugInException {
+ return custom.resolve(principal, requester, depends);
}
/**
return custom.getTTL();
}
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugIn#getAttributeDefinitionDependencyIds()
+ */
+ public String[] getAttributeDefinitionDependencyIds() {
+ return custom.getAttributeDefinitionDependencyIds();
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugIn#getDataConnectorDependencyIds()
+ */
+ public String[] getDataConnectorDependencyIds() {
+ return custom.getDataConnectorDependencyIds();
+ }
}
import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeResolver;
import edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
/**
/**
* @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#resolve(java.security.Principal)
*/
- public Attributes resolve(Principal principal) throws ResolutionPlugInException {
+ public Attributes resolve(Principal principal, String requester, Dependencies depends) throws ResolutionPlugInException {
try {
InitialDirContext context = new InitialDirContext(properties);
import org.w3c.dom.Element;
import edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn;
+import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
/**
/**
* @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#resolve(Principal)
*/
- public Attributes resolve(Principal principal) {
+ public Attributes resolve(Principal principal, String requester, Dependencies depends) {
log.debug("Resolving connector: (" + getId() + ")");
log.debug(getId() + " resolving for principal: (" + principal.getName() + ")");
private static Logger log = Logger.getLogger(SimpleAttributeDefinition.class.getName());
private String connectorMapping;
private String smartScope;
- private String schemaType;
- private String schemaNamespace;
private ValueHandler valueHandler;
/**
<xs:sequence>
<xs:element name="Search">
<xs:complexType>
- <xs:attribute name="query" type="xs:string" use="required"/>
- <xs:attribute name="attributeExtractor" type="xs:string" use="optional"/>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="query" type="xs:string" use="optional"/>
+ <xs:attribute name="attributeExtractor" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:sequence>
<xs:complexType name="BaseAttributeDefinition">
<xs:complexContent>
<xs:extension base="resolver:BaseResolutionPlugIn">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="DataConnectorDependency">
- <xs:complexType>
- <xs:attribute name="requires" type="xs:string" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="AttributeDependency">
- <xs:complexType>
- <xs:attribute name="requires" type="xs:string" use="optional"/>
- </xs:complexType>
- </xs:element>
- </xs:choice>
<xs:attribute name="lifeTime" type="xs:long" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BaseResolutionPlugIn">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="DataConnectorDependency">
+ <xs:complexType>
+ <xs:attribute name="requires" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="AttributeDependency">
+ <xs:complexType>
+ <xs:attribute name="requires" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="cacheTime" type="xs:string" use="optional"/>
</xs:complexType>
/**
* @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#resolve(Principal)
*/
- public Attributes resolve(Principal principal) {
+ public Attributes resolve(Principal principal, String requester, Dependencies depends) {
log.debug("Resolving connector: (" + getId() + ")");
log.debug(getId() + " resolving for principal: (" + principal.getName() + ")");