Added support for data connector failover.
authorcantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sat, 13 Sep 2003 02:38:32 +0000 (02:38 +0000)
committercantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Sat, 13 Sep 2003 02:38:32 +0000 (02:38 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@752 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/aa/attrresolv/AttributeResolver.java
src/edu/internet2/middleware/shibboleth/aa/attrresolv/DataConnectorPlugIn.java
src/edu/internet2/middleware/shibboleth/aa/attrresolv/provider/CustomDataConnector.java
src/edu/internet2/middleware/shibboleth/aa/attrresolv/provider/JNDIDirectoryDataConnector.java

index fd93659..a7f95f7 100644 (file)
@@ -273,6 +273,7 @@ public class AttributeResolver {
                 return;
             }
                }
+        verifyChain.remove(plugIn.getId());
 
                //Recursively go through all AttributeDefinition dependencies and make sure all are registered and consistent.
                depends.clear();
@@ -318,6 +319,51 @@ public class AttributeResolver {
                                return;
                        }
                }
+        verifyChain.remove(plugIn.getId());
+        
+        //Check the failover dependency, if there is one.
+        if (plugIn instanceof DataConnectorPlugIn) {
+            String key = ((DataConnectorPlugIn)plugIn).getFailoverDependencyId();
+            if (key != null) {
+                if (!plugIns.containsKey(key)) {
+                    log.error(
+                        "The PlugIn ("
+                            + plugIn.getId()
+                            + ") is inconsistent.  It depends on a PlugIn ("
+                            + key
+                            + ") that is not registered.");
+                    inconsistent.add(plugIn.getId());
+                    return;
+                }
+
+                ResolutionPlugIn dependent = lookupPlugIn(key);
+                if (!(dependent instanceof DataConnectorPlugIn)) {
+                    log.error(
+                        "The PlugIn ("
+                            + plugIn.getId()
+                            + ") is inconsistent.  It depends on a fail-over PlugIn ("
+                            + key
+                            + ") that is not a DataConnectorPlugIn.");
+                    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 inconsistent.");
+                    inconsistent.add(plugIn.getId());
+                    return;
+                }
+            }
+        }
+        verifyChain.remove(plugIn.getId());
        }
 
        private void registerPlugIn(ResolutionPlugIn connector, String id) throws DuplicatePlugInException {
@@ -473,21 +519,32 @@ public class AttributeResolver {
         }
 
         //Resolve the connector
-        Attributes resolvedAttributes = currentDefinition.resolve(principal, requester, depends);
-
-        //Cache for this request
-        requestCache.put(currentDefinition.getId(), resolvedAttributes);
+        try {
+            Attributes resolvedAttributes = currentDefinition.resolve(principal, requester, depends);
 
-        //Add attribute resolution to cache
-        if (currentDefinition.getTTL() > 0) {
-            resolverCache.cacheConnectorResolution(
-                principal,
-                currentDefinition.getId(),
-                currentDefinition.getTTL(),
-                resolvedAttributes);
+            //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;
+        }
+        catch (ResolutionPlugInException e) {
+            // Something went wrong, so check for a fail-over...
+            if (currentDefinition.getFailoverDependencyId() != null) {
+                return resolveConnector(
+                    currentDefinition.getFailoverDependencyId(), principal, requester, requestCache, requestedAttributes
+                    );
+            }
+            throw e;
         }
-        
-        return resolvedAttributes;
     }
 
        private void resolveAttribute(
index b9bf4b3..ca87014 100644 (file)
@@ -63,6 +63,13 @@ import javax.naming.directory.Attributes;
 public interface DataConnectorPlugIn extends ResolutionPlugIn {
        
     /**
+     * Returns the name of a data connector to resolve if this one fails.
+     * 
+     * @return String an Id
+     */
+    public String getFailoverDependencyId();
+
+    /**
      * Resolves the values of a data connector.
      * 
      * @param principal The principal for which the connector should be resolved
index e5efe7a..efd7534 100644 (file)
@@ -129,4 +129,11 @@ public class CustomDataConnector implements DataConnectorPlugIn {
     public String[] getDataConnectorDependencyIds() {
         return custom.getDataConnectorDependencyIds();
     }
+    
+    /**
+     * @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#getFailoverDependencyId()
+     */
+    public String getFailoverDependencyId() {
+        return custom.getFailoverDependencyId();
+    }
 }
index 6b99a56..5279f29 100644 (file)
@@ -82,18 +82,25 @@ public class JNDIDirectoryDataConnector extends BaseResolutionPlugIn implements
        protected String searchFilter;
        protected Properties properties;
        protected SearchControls controls;
-
-       /**
-        * Constructs a DataConnector based on DOM configuration.
-        * 
-        * @param e a &lt;JNDIDirectoryDataConnector /&gt; DOM Element as specified by 
-        * urn:mace:shibboleth:resolver:1.0
-        * 
-        * @throws ResolutionPlugInException if the PlugIn cannot be initialized
-        */
+    protected String failover = null;
+
+    /**
+     * Constructs a DataConnector based on DOM configuration.
+     * 
+     * @param e a &lt;JNDIDirectoryDataConnector /&gt; DOM Element as specified by 
+     * urn:mace:shibboleth:resolver:1.0
+     * 
+     * @throws ResolutionPlugInException if the PlugIn cannot be initialized
+     */
        public JNDIDirectoryDataConnector(Element e) throws ResolutionPlugInException {
 
                super(e);
+        
+        NodeList failoverNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "FailoverDependency");
+        if (failoverNodes.getLength() > 0) {
+            failover = ((Element)failoverNodes.item(0)).getAttribute("requires");
+        }
+        
                NodeList searchNodes = e.getElementsByTagNameNS(AttributeResolver.resolverNamespace, "Search");
                if (searchNodes.getLength() != 1) {
                        log.error("JNDI Directory Data Connector requires a \"Search\" specification.");
@@ -127,13 +134,13 @@ public class JNDIDirectoryDataConnector extends BaseResolutionPlugIn implements
                                throw new ResolutionPlugInException("Property is malformed.");
                        }
                }
-               
-               //Fail-fast connection test
+
+        //Fail-fast connection test
                InitialDirContext context = null;
                try {
                        context = new InitialDirContext(properties);
                        log.debug("JNDI Directory context activated.");
-
+                       
                } catch (NamingException e1) {
                        log.error("Failed to startup directory context: " + e1);
                        throw new ResolutionPlugInException("Failed to startup directory context.");
@@ -149,11 +156,11 @@ public class JNDIDirectoryDataConnector extends BaseResolutionPlugIn implements
                }
        }
 
-       /**
-        * Create JNDI search controls based on DOM configuration
-        * @param searchNode a &lt;Controls /&gt; DOM Element as specified by 
-        * urn:mace:shibboleth:resolver:1.0
-        */
+    /**
+     * Create JNDI search controls based on DOM configuration
+     * @param searchNode a &lt;Controls /&gt; DOM Element as specified by 
+     * urn:mace:shibboleth:resolver:1.0
+     */
        protected void defineSearchControls(Element searchNode) {
 
                controls = new SearchControls();
@@ -233,6 +240,7 @@ public class JNDIDirectoryDataConnector extends BaseResolutionPlugIn implements
                try {
                        context = new InitialDirContext(properties);
                        NamingEnumeration enum = null;
+
                        try {
                                enum = context.search("", searchFilter.replaceAll("%PRINCIPAL%", principal.getName()), controls);
                        } catch (CommunicationException e) {
@@ -276,4 +284,10 @@ public class JNDIDirectoryDataConnector extends BaseResolutionPlugIn implements
                }
        }
 
+    /**
+     * @see edu.internet2.middleware.shibboleth.aa.attrresolv.DataConnectorPlugIn#getFailoverDependencyId()
+     */
+    public String getFailoverDependencyId() {
+        return failover;
+    }
 }