Initial implementation.
authordfisher <dfisher@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 12 Feb 2007 03:01:11 +0000 (03:01 +0000)
committerdfisher <dfisher@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 12 Feb 2007 03:01:11 +0000 (03:01 +0000)
Still missing some glue.

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2147 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/profile/saml2/AttributeQuery.java

index 1792e4c..917c9ae 100644 (file)
  */
 package edu.internet2.middleware.shibboleth.idp.profile.saml2;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
+
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import edu.internet2.middleware.shibboleth.common.profile.ProfileHandler;
+import edu.internet2.middleware.shibboleth.common.attribute.Attribute;
+import edu.internet2.middleware.shibboleth.common.attribute.AttributeEncoder;
+import edu.internet2.middleware.shibboleth.common.attribute.SAML2AttributeEncoder;
+import edu.internet2.middleware.shibboleth.common.attribute.resolver.ResolutionContext;
+import edu.internet2.middleware.shibboleth.idp.profile.AbstractProfileHandler;
+
+import org.joda.time.DateTime;
+
+import org.opensaml.common.SAMLObjectBuilder;
+import org.opensaml.common.SAMLVersion;
+
+import org.opensaml.saml2.core.Assertion;
+import org.opensaml.saml2.core.AttributeStatement;
+import org.opensaml.saml2.core.Conditions;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.Subject;
 
 /**
- * SAML 2.0 Attribute Query profile handler
+ * SAML 2.0 Attribute Query profile handler.
  */
-public class AttributeQuery implements ProfileHandler {
+public class AttributeQuery extends AbstractProfileHandler {
 
+    /** SAML Version for this profile handler. */
+    public static final SAMLVersion SAML_VERSION = SAMLVersion.VERSION_20;
+    
+    
     /** {@inheritDoc} */
     public boolean processRequest(ServletRequest request, ServletResponse response) throws ServletException {
-        // TODO Auto-generated method stub
-        return false;
+        // call decode method on decoder
+        getDecoder().decode(request);
+        // get SAMLMessage from the decoder
+        final org.opensaml.saml2.core.AttributeQuery message =
+            (org.opensaml.saml2.core.AttributeQuery) getDecoder().getSAMLMessage();
+        
+        // intersect requested attributes with released attributes
+        final List<org.opensaml.saml2.core.Attribute> requestedAttributes = message.getAttributes();
+        final Set<String> releasedAttributes = new HashSet<String>(requestedAttributes.size());
+        for (org.opensaml.saml2.core.Attribute a: requestedAttributes) {
+            releasedAttributes.add(a.getName());            
+        }
+        List<String> releaseableAttributes = getFilterEngine().getReleaseableAttributes(getDecoder().getIssuer());
+        releasedAttributes.retainAll(releaseableAttributes);
+        // TODO go to metadata for other attributes
+
+        // create resolution context from the resolver, using nameid element from the attribute query
+        ResolutionContext context = getAttributeResolver().createResolutionContext(
+                message.getSubject().getNameID(), getDecoder().getIssuer(), request);
+        // call Attribute resolver
+        Set<Attribute> resolvedAttributes = getAttributeResolver().resolveAttributes(releasedAttributes, context);
+        
+        // construct attribute response
+        List<org.opensaml.saml2.core.Attribute> encodedAttributes = new ArrayList<org.opensaml.saml2.core.Attribute>();
+        for (Attribute a: resolvedAttributes) {
+            for (AttributeEncoder<Attribute, org.opensaml.saml2.core.Attribute> e: a.getEncoders()) {
+                if (e instanceof SAML2AttributeEncoder) {
+                    // get encoder and call encode method
+                    encodedAttributes.add(e.encode(a));
+                    break;                
+                }
+            }
+        }
+
+        Response samlResponse = buildResponse(getDecoder().getIssuer(), new DateTime(), encodedAttributes);
+        getEncoder().setSAMLMessage(response);
+        getEncoder().encode();
+        return true;
+    }
+    
+    
+    /**
+     * This builds the response for this SAML request.
+     * 
+     *  @param issuer <code>String</code>
+     *  @param issueInstant <code>DateTime</code>
+     *  @param encodedAttributes <code>List</code> of attributes
+     *  @return <code>Response</code>
+     */
+    private Response buildResponse(
+            String issuer, DateTime issueInstant, List<org.opensaml.saml2.core.Attribute> encodedAttributes) {
+        SAMLObjectBuilder<Response> responseBuilder = (SAMLObjectBuilder<Response>) getBuilderFactory().getBuilder(
+            Response.DEFAULT_ELEMENT_NAME);
+        Response response = responseBuilder.buildObject();
+        response.setVersion(SAML_VERSION);
+        response.setID(getIdGenerator().generateIdentifier());
+        response.setInResponseTo(issuer);
+        response.setIssueInstant(issueInstant);
+
+        //response.setDestination(String);
+        //response.setConsent(String);
+        //response.setIssuer(Issuer);
+        //response.setExtensions(Extensions);
+        
+        response.setStatus(buildStatus());
+        response.getAssertions().add(buildAssertion(issueInstant, encodedAttributes));        
+    }
+    
+
+    /**
+     * This builds the status response for this SAML request.
+     * 
+     *  @return <code>Status</code>
+     */
+    private Status buildStatus() {
+        // build status
+        SAMLObjectBuilder statusBuilder = (SAMLObjectBuilder<Status>) getBuilderFactory().getBuilder(
+                Status.DEFAULT_ELEMENT_NAME);
+        Status status = statusBuilder.buildObject();
+
+        // build status code
+        SAMLObjectBuilder statusCodeBuilder = (SAMLObjectBuilder<StatusCode>) getBuilderFactory().getBuilder(
+                StatusCode.DEFAULT_ELEMENT_NAME);
+        StatusCode statusCode = statusCodeBuilder.buildObject();
+        statusCode.setValue(StatusCode.SUCCESS_URI);
+        status.setStatusCode(statusCode);
+        return status;
+    }
+    
+    
+    /**
+     * This builds the assertion for this SAML request.
+     * 
+     *  @param issueInstant <code>DateTime</code>
+     *  @param encodedAttributes <code>List</code> of attributes
+     *  @return <code>Assertion</code>
+     */
+    private Assertion buildAssertion(DateTime issueInstant, List<org.opensaml.saml2.core.Attribute> encodedAttributes) {
+        // build assertions
+        SAMLObjectBuilder assertionBuilder = (SAMLObjectBuilder<Assertion>) getBuilderFactory().getBuilder(
+                Assertion.DEFAULT_ELEMENT_NAME);
+        Assertion assertion = assertionBuilder.buildObject();
+        assertion.setID(getIdGenerator().generateIdentifier());
+        assertion.setIssueInstant(issueInstant);
+        assertion.setVersion(SAML_VERSION);
+        // TODO assertion.setIssuer();
+
+        // build subject
+        SAMLObjectBuilder subjectBuilder = (SAMLObjectBuilder<Subject>) getBuilderFactory().getBuilder(
+                Subject.DEFAULT_ELEMENT_NAME);
+        Subject subject = subjectBuilder.buildObject();
+        // TOTO subject.setNameID(NameID); <- comes from request
+        assertion.setSubject(subject);
+
+        // build conditions
+        SAMLObjectBuilder conditionsBuilder = (SAMLObjectBuilder<Conditions>) getBuilderFactory().getBuilder(
+                Conditions.DEFAULT_ELEMENT_NAME);
+        Conditions conditions = conditionsBuilder.buildObject();
+        conditions.setNotBefore(issueInstant);
+        //TODO conditions.setNotOnOrAfter();
+        //TODO add additional conditions : conditions.getConditions().add(Condition); 
+        assertion.setConditions(conditions);
+
+        // build attribute statement
+        SAMLObjectBuilder statementBuilder = (SAMLObjectBuilder<AttributeStatement>) getBuilderFactory().getBuilder(
+                AttributeStatement.DEFAULT_ELEMENT_NAME);
+        AttributeStatement statement = statementBuilder.buildObject();
+        statement.getAttributes().addAll(encodedAttributes);
+        assertion.getAttributeStatements().add(statement);
+        
+        return assertion;
     }
 }
\ No newline at end of file