001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: FSRequest.java,v 1.3 2008/06/25 05:46:45 qcheng Exp $ 026 * 027 */ 028 029/** 030 * Portions Copyrighted 2012 ForgeRock AS 031 */ 032package com.sun.identity.federation.message; 033 034import java.util.List; 035import java.util.Collections; 036import java.util.ArrayList; 037import java.util.Iterator; 038import java.util.StringTokenizer; 039import org.w3c.dom.Attr; 040import org.w3c.dom.Element; 041import org.w3c.dom.Node; 042import org.w3c.dom.NodeList; 043import org.w3c.dom.NamedNodeMap; 044import org.w3c.dom.Document; 045import com.sun.identity.saml.common.SAMLConstants; 046import com.sun.identity.saml.common.SAMLException; 047import com.sun.identity.saml.common.SAMLResponderException; 048import com.sun.identity.saml.common.SAMLRequesterException; 049import com.sun.identity.saml.common.SAMLRequestVersionTooHighException; 050import com.sun.identity.saml.common.SAMLRequestVersionTooLowException; 051import com.sun.identity.saml.xmlsig.XMLSignatureManager; 052import com.sun.identity.saml.protocol.AssertionArtifact; 053import com.sun.identity.saml.protocol.AttributeQuery; 054import com.sun.identity.saml.protocol.AuthenticationQuery; 055import com.sun.identity.saml.protocol.AuthorizationDecisionQuery; 056import com.sun.identity.saml.protocol.Request; 057import com.sun.identity.saml.protocol.Query; 058import com.sun.identity.shared.DateUtils; 059import com.sun.identity.saml.assertion.AssertionIDReference; 060import com.sun.identity.federation.common.FSUtils; 061import com.sun.identity.federation.common.IFSConstants; 062import com.sun.identity.shared.xml.XMLUtils; 063 064/** 065 * This class represents a Liberty <code>Request</code>. 066 * It extends from the abstract base class <code>AbstractRequest</code>. 067 * 068 * @supported.all.api 069 */ 070public class FSRequest extends Request { 071 /* 072 * data members 073 */ 074 protected String id = null; 075 076 077 /** 078 * Returns the value of <code>id</code> attribute. 079 * 080 * @return the value of <code>id</code> attribute. 081 * @see #setID(String) 082 */ 083 public String getID() { 084 return id; 085 } 086 087 /** 088 * Sets the value of <code>id</code> attribute. 089 * 090 * @param id the value of <code>id</code> attribute. 091 * @see #getID() 092 */ 093 094 public void setID(String id) { 095 this.id = id; 096 } 097 098 /* 099 * Default Constructor. 100 */ 101 protected FSRequest() { 102 } 103 104 105 /** 106 * Constructor creates <code>Request</code> object. This 107 * shall only be used at the client side to construct a 108 * <code>Request</code> object. 109 * NOTE: The content here is just the body for the Request. The 110 * constructor will add <code>MajorVersion</code>, 111 * <code>MinorVersion</code>, etc. to form a complete Request. 112 * 113 * @param requestId the request identifier, if this 114 * value is null then one will be generated. 115 * @param query <code>AuthenticationQuery</code> to be included in 116 * the Request. 117 * @throws <code>SAMLException</code> on error. 118 */ 119 public FSRequest(String requestId, Query query) throws SAMLException { 120 super(requestId, query); 121 } 122 123 /** 124 * Constructor creates <code>Request</code> object. This 125 * shall only be used at the client side to construct a 126 * <code>Request</code> object. 127 * NOTE: The content here is just the body for the Request. The 128 * constructor will add <code>MajorVersion</code>, 129 * <code>MinorVersion</code>, etc. to form a complete Request. 130 * 131 * @param requestId the request identifier, if this 132 * value is null then one will be generated. 133 * @param contents a <code>List</code> of objects that are the contents 134 * of Request that the client wants to send to the server. 135 * It could be an : 136 * <code>AuthenticationQuery</code>, 137 * <code>AuthorizationDecisionQuery</code>, 138 * <code>AttributeQuery</code>, 1 or more 139 * <code>AssertionIDReference</code>, or 1 or more of 140 * <code>AssertionArtifact</code>. 141 * @throws <code>SAMLException</code> throws errors on exception. 142 */ 143 public FSRequest(String requestId, List contents) throws SAMLException { 144 super(requestId, contents); 145 } 146 147 148 /** 149 * Returns the <code>MinorVersion</code>. 150 * 151 * @return the <code>MinorVersion</code>. 152 * @see #setMinorVersion(int) 153 */ 154 public int getMinorVersion() { 155 return minorVersion; 156 } 157 158 /** 159 * Sets the <code>MinorVersion</code>. 160 * 161 * @param version the <code>MinorVersion</code>. 162 * @see #getMinorVersion() 163 */ 164 public void setMinorVersion(int version) { 165 minorVersion = version; 166 } 167 168 /** 169 * Parses the <code>XML</code> Document String to construct a 170 * <code>Request</code> object. This method shall only be used at the server 171 * side to reconstruct a Request object based on the XML document 172 * received from client. 173 * 174 * @param xml the <code>XML</code> Document string. 175 * @return the <code>Request</code> object. 176 * @throws <code>SAMLException</code> on error. 177 */ 178 public static Request parseXML(String xml) throws SAMLException { 179 // parse the xml string 180 Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug); 181 Element root = doc.getDocumentElement(); 182 return new FSRequest(root); 183 } 184 185 /** 186 * Constructor creates a <code>FSRequest</code> object from 187 * a <code>XML</code> Document Element. 188 * 189 * @param root the <code>XML</code> Document Element. 190 * @throws <code>SAMLException</code> on error. 191 */ 192 public FSRequest(Element root) throws SAMLException { 193 // Make sure this is a Request 194 String tag = null; 195 if (root == null) { 196 FSUtils.debug.message("Request(Element): null input."); 197 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 198 "nullInput",null); 199 } 200 if (((tag = root.getLocalName()) == null) || 201 (!tag.equals("Request"))) { 202 FSUtils.debug.message("Request(Element): wrong input"); 203 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 204 "wrongInput",null); 205 } 206 207 id = root.getAttribute("id"); 208 List signs = XMLUtils.getElementsByTagNameNS1(root, 209 SAMLConstants.XMLSIG_NAMESPACE_URI, 210 SAMLConstants.XMLSIG_ELEMENT_NAME); 211 int signsSize = signs.size(); 212 if (signsSize == 1) { 213 XMLSignatureManager manager = XMLSignatureManager.getInstance(); 214 if (id == null) { 215 valid = manager.verifyXMLSignature(root, 216 IFSConstants.REQUEST_ID, null); 217 } else { 218 valid = manager.verifyXMLSignature(root); 219 } 220 if (!valid) { 221 if (FSUtils.debug.messageEnabled()) { 222 FSUtils.debug.message("Request(Element): couldn't verify" 223 + " Request's signature."); 224 } 225 } 226 xmlString = XMLUtils.print(root); 227 signed = true; 228 } else if (signsSize != 0) { 229 if (FSUtils.debug.messageEnabled()) { 230 FSUtils.debug.message("Request(Element): included more than" 231 + " one Signature element."); 232 } 233 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 234 "moreElement",null); 235 } 236 237 // Attribute RequestID 238 requestID = root.getAttribute("RequestID"); 239 if ((requestID == null) || (requestID.length() == 0)) { 240 if (FSUtils.debug.messageEnabled()) { 241 FSUtils.debug.message("Request(Element): Request doesn't " 242 + "have a RequestID."); 243 } 244 String[] args = { IFSConstants.REQUEST_ID }; 245 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 246 "missingAttribute",args); 247 } 248 249 // Attribute MajorVersion 250 parseMajorVersion(root.getAttribute("MajorVersion")); 251 252 // Attribute MinorVersion 253 parseMinorVersion(root.getAttribute("MinorVersion")); 254 255 // Attribute IssueInstant 256 String instantString = root.getAttribute("IssueInstant"); 257 if ((instantString == null) || (instantString.length() == 0)) { 258 FSUtils.debug.message("Request(Element): missing IssueInstant"); 259 String[] args = { IFSConstants.ISSUE_INSTANT }; 260 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 261 "missingAttribute",args); 262 } else { 263 try { 264 issueInstant = DateUtils.stringToDate(instantString); 265 } catch (Exception e) { 266 FSUtils.debug.message( 267 "Request(Element): could not parse IssueInstant", e); 268 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 269 "wrongInput",null); 270 } 271 } 272 273 // get the contents of the request 274 NodeList contentnl = root.getChildNodes(); 275 Node child; 276 String nodeName; 277 String respondWith; 278 for (int i = 0, length = contentnl.getLength(); i < length; i++) { 279 child = contentnl.item(i); 280 if ((nodeName = child.getLocalName()) != null) { 281 if (nodeName.equals("RespondWith")) { 282 respondWith = XMLUtils.getElementValue((Element) child); 283 if (respondWith.length() == 0) { 284 if (FSUtils.debug.messageEnabled()) { 285 FSUtils.debug.message("Request(Element): wrong " 286 + "RespondWith value."); 287 } 288 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 289 "wrongInput",null); 290 } 291 if (respondWiths == Collections.EMPTY_LIST) { 292 respondWiths = new ArrayList(); 293 } 294 respondWiths.add(respondWith); 295 } else if (nodeName.equals("Signature")) { 296 signature = (Element) child; 297 } else if (nodeName.equals("AuthenticationQuery")) { 298 // make sure the content is not assigned already 299 if (contentType != NOT_SUPPORTED) { 300 if (FSUtils.debug.messageEnabled()) { 301 FSUtils.debug.message("Request(Element): should" 302 + "contain only one AuthenticationQuery."); 303 } 304 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 305 "wrongInput",null); 306 } 307 contentType = AUTHENTICATION_QUERY; 308 query = new AuthenticationQuery((Element) child); 309 } else if (nodeName.equals("AuthorizationDecisionQuery")) { 310 // make sure content is not assigned already 311 if (contentType != NOT_SUPPORTED) { 312 if (FSUtils.debug.messageEnabled()) { 313 FSUtils.debug.message("Request(Element): should" 314 + "contain only one " 315 + "AuthorizationDecisionQuery."); 316 } 317 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 318 "wrongInput",null); 319 } 320 contentType = AUTHORIZATION_DECISION_QUERY; 321 query = new AuthorizationDecisionQuery((Element) child); 322 } else if (nodeName.equals("AttributeQuery")) { 323 // make sure content is not assigned already 324 if (contentType != NOT_SUPPORTED) { 325 if (FSUtils.debug.messageEnabled()) { 326 FSUtils.debug.message("Request(Element): should" 327 + "contain only one AttributeQuery."); 328 } 329 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 330 "wrongInput",null); 331 } 332 contentType = ATTRIBUTE_QUERY; 333 query = new AttributeQuery((Element) child); 334 } else if (nodeName.equals("AssertionIDReference")) { 335 // make sure the content has no other elements assigned 336 if ((contentType != NOT_SUPPORTED) && 337 (contentType != ASSERTION_ID_REFERENCE)) { 338 if (FSUtils.debug.messageEnabled()) { 339 FSUtils.debug.message("Request(Element): " 340 + "contained mixed contents."); 341 } 342 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 343 "wrongInput",null); 344 } 345 contentType = ASSERTION_ID_REFERENCE; 346 if (assertionIDRefs == Collections.EMPTY_LIST) { 347 assertionIDRefs = new ArrayList(); 348 } 349 assertionIDRefs.add(new AssertionIDReference( 350 XMLUtils.getElementValue((Element) child))); 351 } else if (nodeName.equals("AssertionArtifact")) { 352 // make sure the content has no other elements assigned 353 if ((contentType != NOT_SUPPORTED) && 354 (contentType != ASSERTION_ARTIFACT)) { 355 if (FSUtils.debug.messageEnabled()) { 356 FSUtils.debug.message("Request(Element): " 357 + "contained mixed contents."); 358 } 359 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 360 "wrongInput",null); 361 } 362 contentType = ASSERTION_ARTIFACT; 363 if (artifacts == Collections.EMPTY_LIST) { 364 artifacts = new ArrayList(); 365 } 366 artifacts.add(new AssertionArtifact( 367 XMLUtils.getElementValue((Element) child))); 368 } else if (nodeName.equals("Query") || 369 nodeName.equals("SubjectQuery")) { 370 parseQuery(child); 371 } else { 372 if (FSUtils.debug.messageEnabled()) { 373 FSUtils.debug.message("Request(Element): invalid" 374 + " node" + nodeName); 375 } 376 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 377 "wrongInput",null); 378 } // check nodeName 379 } // if nodeName != null 380 } // done for the nodelist loop 381 382 if (contentType == NOT_SUPPORTED) { 383 FSUtils.debug.message("Request: empty content."); 384 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 385 "wrongInput",null); 386 } 387 } 388 389 /* Returns the value of <code>RespondWith</code> attribute. 390 * 391 * @return value of the <code>RespondWith</code> attribute. 392 * @throws <code>SAMLException</code> on error. 393 */ 394 private String checkAndGetRespondWith(String respondWith) 395 throws SAMLException { 396 if ((respondWith == null) || (respondWith.length() == 0)) { 397 FSUtils.debug.message("Request: empty RespondWith Value."); 398 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 399 "wrongInput",null); 400 } 401 402 if (respondWith.indexOf(":") == -1) { 403 return (SAMLConstants.ASSERTION_PREFIX + respondWith); 404 } else { 405 StringTokenizer st = new StringTokenizer(respondWith, ":"); 406 if (st.countTokens() != 2) { 407 FSUtils.debug.message("Request: wrong RespondWith value."); 408 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 409 "wrongInput",null); 410 } 411 st.nextToken(); 412 String temp = st.nextToken().trim(); 413 if (temp.length() == 0) { 414 FSUtils.debug.message("Request: wrong RespondWith value."); 415 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 416 "wrongInput",null); 417 } 418 return (SAMLConstants.ASSERTION_PREFIX + temp); 419 } 420 } 421 422 423 /** 424 * Sets the <code>MajorVersion</code> by parsing the version string. 425 * 426 * @param majorVer a String representing the <code>MajorVersion</code> to 427 * be set. 428 * @throws <code>FSMsgException</code> on error. 429 */ 430 431 private void parseMajorVersion(String majorVer) throws SAMLException { 432 try { 433 majorVersion = Integer.parseInt(majorVer); 434 } catch (NumberFormatException e) { 435 if (FSUtils.debug.messageEnabled()) { 436 FSUtils.debug.message("Request(Element): invalid " 437 + "MajorVersion", e); 438 } 439 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 440 "wrongInput",null); 441 } 442 443 if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) { 444 if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) { 445 if (FSUtils.debug.messageEnabled()) { 446 FSUtils.debug.message("Request(Element):MajorVersion of " 447 + "the Request is too high."); 448 } 449 throw new SAMLRequestVersionTooHighException( 450 FSUtils.BUNDLE_NAME,"requestVersionTooHigh",null); 451 } else { 452 if (FSUtils.debug.messageEnabled()) { 453 FSUtils.debug.message("Request(Element):MajorVersion of " 454 + "the Request is too low."); 455 } 456 throw new SAMLRequestVersionTooLowException(FSUtils.BUNDLE_NAME, 457 "requestVersionTooLow",null); 458 } 459 } 460 } 461 462 /** 463 * Sets the <code>MinorVersion</code> by parsing the version string. 464 * 465 * @param minorVer a String representing the <code>MinorVersion</code> to 466 * be set. 467 * @throws <code>SAMLException</code> when the version mismatchs. 468 */ 469 private void parseMinorVersion(String minorVer) throws SAMLException { 470 try { 471 minorVersion = Integer.parseInt(minorVer); 472 } catch (NumberFormatException e) { 473 if (FSUtils.debug.messageEnabled()) { 474 FSUtils.debug.message("Request(Element): invalid " 475 + "MinorVersion", e); 476 } 477 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 478 "wrongInput",null); 479 } 480 481 if(minorVersion > IFSConstants.FF_12_SAML_PROTOCOL_MINOR_VERSION) { 482 FSUtils.debug.error("Request(Element): MinorVersion" 483 + " of the Request is too high."); 484 throw new SAMLRequestVersionTooHighException(FSUtils.BUNDLE_NAME, 485 "requestVersionTooHigh",null); 486 } else if (minorVersion < 487 IFSConstants.FF_11_SAML_PROTOCOL_MINOR_VERSION) { 488 FSUtils.debug.error("Request(Element): MinorVersion" 489 + " of the Request is too low."); 490 throw new SAMLRequestVersionTooLowException(FSUtils.BUNDLE_NAME, 491 "requestVersionTooLow",null); 492 } 493 } 494 495 /** 496 * Parses the Query or <code>SubjectQuery</code> represented by 497 * a DOM tree Node. It then checks and sets data members if it is a 498 * supported query, such as <code>AuthenticationQuery</code>, 499 * <code>AttributeQeury</code>, or <code>AuthorizationDecisionQuery</code>. 500 * 501 * @param child a <code>DOM</code> Node. 502 * @throws <code>SAMLException</code> if the <code>Query</code> is invalid. 503 */ 504 private void parseQuery(Node child) throws SAMLException { 505 NamedNodeMap nm = child.getAttributes(); 506 int len = nm.getLength(); 507 String attrName; 508 String attrValue; 509 Attr attr; 510 boolean found = false; 511 for (int j = 0; j < len; j++) { 512 attr = (Attr) nm.item(j); 513 attrName = attr.getLocalName(); 514 if ((attrName != null) && (attrName.equals("type"))) { 515 attrValue = attr.getNodeValue(); 516 if (attrValue.equals("AuthenticationQueryType")) { 517 if (contentType != NOT_SUPPORTED) { 518 if (FSUtils.debug.messageEnabled()) { 519 FSUtils.debug.message("Request(Element): should" 520 + " contain only one AuthenticationQuery."); 521 } 522 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 523 "wrongInput",null); 524 } 525 contentType = AUTHENTICATION_QUERY; 526 query = new AuthenticationQuery((Element) child); 527 } else if (attrValue.equals( 528 "AuthorizationDecisionQueryType")) { 529 if (contentType != NOT_SUPPORTED) { 530 if (FSUtils.debug.messageEnabled()) { 531 FSUtils.debug.message("Request(Element): should " 532 + "contain one " 533 + "AuthorizationDecisionQuery."); 534 } 535 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 536 "wrongInput",null); 537 } 538 contentType = AUTHORIZATION_DECISION_QUERY; 539 query = new AuthorizationDecisionQuery((Element) child); 540 } else if (attrValue.equals("AttributeQueryType")) { 541 if (contentType != NOT_SUPPORTED) { 542 if (FSUtils.debug.messageEnabled()) { 543 FSUtils.debug.message("Request(Element): should " 544 + "contain one AttributeQuery."); 545 } 546 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 547 "wrongInput",null); 548 } 549 contentType = ATTRIBUTE_QUERY; 550 query = new AttributeQuery((Element) child); 551 } else { 552 if (FSUtils.debug.messageEnabled()) { 553 FSUtils.debug.message("Request(Element): This type of" 554 + " " + attrName + " is not supported."); 555 } 556 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 557 "queryNotSupported",null); 558 } // check typevalue 559 found = true; 560 break; 561 } // if found type attribute 562 } // end attribute for loop 563 // if not found type 564 if (!found) { 565 if (FSUtils.debug.messageEnabled()) { 566 FSUtils.debug.message("Request(Element): missing" 567 + " xsi:type definition in " + child.getLocalName()); 568 } 569 throw new SAMLRequesterException(FSUtils.BUNDLE_NAME, 570 "wrongInput",null); 571 } 572 } 573 574 /** 575 * Creates a String representation of the <code><samlp:Request></code> 576 * element. 577 * 578 * @return a <code>XML</code> String representing the request. 579 */ 580 public String toXMLString() { 581 return toXMLString(true, true); 582 } 583 584 /** 585 * Creates a String representation of the <code><samlp:Request></code> 586 * element. 587 * 588 * @param includeNS Determines whether or not the names pace qualifier 589 * is prepended to the Element when converted 590 * @param declareNS Determines whether or not the name space is declared 591 * within the Element. 592 * @return a string containing the valid XML for this object. 593 */ 594 public String toXMLString(boolean includeNS, boolean declareNS) { 595 return toXMLString(includeNS, declareNS, false); 596 } 597 598 /** 599 * Creates a String representation of the <code><samlp:Request></code> 600 * element. 601 * 602 * @param includeNS Determines whether or not the name space qualifier 603 * is prepended to the Element when converted 604 * @param declareNS Determines whether or not the name space is declared 605 * within the Element. 606 * @param includeHeader Determines whether the output include the XML 607 * declaration header. 608 * @return a string containing the valid XML for this object. 609 */ 610 public String toXMLString(boolean includeNS,boolean declareNS, 611 boolean includeHeader) { 612 if (signed && (xmlString != null)) { 613 return xmlString; 614 } 615 616 StringBuffer xml = new StringBuffer(300); 617 if (includeHeader) { 618 xml.append("<?xml version=\"1.0\" encoding=\""). 619 append(SAMLConstants.DEFAULT_ENCODING).append("\" ?>\n"); 620 } 621 String prefix = ""; 622 String libprefix = ""; 623 String uri = ""; 624 String liburi = ""; 625 String uriXSI=""; 626 if (includeNS) { 627 prefix = SAMLConstants.PROTOCOL_PREFIX; 628 libprefix = IFSConstants.LIB_PREFIX; 629 } 630 if (declareNS) { 631 uri = SAMLConstants.PROTOCOL_NAMESPACE_STRING; 632 if(minorVersion == IFSConstants.FF_12_SAML_PROTOCOL_MINOR_VERSION){ 633 liburi = IFSConstants.LIB_12_NAMESPACE_STRING; 634 } else { 635 liburi = IFSConstants.LIB_NAMESPACE_STRING; 636 } 637 uriXSI = IFSConstants.XSI_NAMESPACE_STRING; 638 } 639 640 String instantString = DateUtils.toUTCDateFormat(issueInstant); 641 642 xml.append("<").append(prefix).append("Request").append(uri). 643 //append(" xmlns=\"http://www.w3.org/2000/xmlns/\"").append(uri). 644 append(" ").append(liburi).append(" ").append(uriXSI); 645 if(minorVersion == IFSConstants.FF_11_SAML_PROTOCOL_MINOR_VERSION) { 646 if(id != null && !(id.length() == 0)){ 647 xml.append(" id=\"").append(id).append("\""); 648 } 649 } 650 xml.append(" RequestID=\"").append(requestID).append("\""). 651 append(" MajorVersion=\"").append(majorVersion).append("\""). 652 append(" MinorVersion=\"").append(minorVersion).append("\""). 653 append(" IssueInstant=\"").append(instantString).append("\""); 654 655 if(minorVersion == IFSConstants.FF_11_SAML_PROTOCOL_MINOR_VERSION) { 656 xml.append(" xsi:type").append("=\"").append(libprefix). 657 append("SignedSAMLRequestType").append("\""); 658 } 659 xml.append(">"); 660 if((respondWiths != null) && (respondWiths != Collections.EMPTY_LIST)){ 661 Iterator i = respondWiths.iterator(); 662 String respondWith = null; 663 while (i.hasNext()) { 664 respondWith = (String) i.next(); 665 xml.append("<").append(prefix).append("RespondWith>"); 666 if (respondWith.startsWith(SAMLConstants.ASSERTION_PREFIX)) { 667 xml.append(respondWith); 668 } else { 669 try { 670 xml.append(checkAndGetRespondWith(respondWith)); 671 } catch (SAMLException e) { 672 FSUtils.debug.error("Request.toString: ", e); 673 xml.append(respondWith); 674 } 675 } 676 xml.append("</").append(prefix).append("RespondWith>"); 677 } 678 } 679 680 if (signed) { 681 if (signatureString != null) { 682 xml.append(signatureString); 683 } else if (signature != null) { 684 signatureString = XMLUtils.print(signature); 685 xml.append(signatureString); 686 } 687 } 688 Iterator j; 689 switch (contentType) { 690 case AUTHENTICATION_QUERY: 691 xml.append(((AuthenticationQuery)query) 692 .toString(includeNS, false)); 693 break; 694 case AUTHORIZATION_DECISION_QUERY: 695 xml.append(((AuthorizationDecisionQuery)query) 696 .toString(includeNS,false)); 697 break; 698 case ATTRIBUTE_QUERY: 699 xml.append(((AttributeQuery)query).toString(includeNS, false)); 700 break; 701 case ASSERTION_ID_REFERENCE: 702 j = assertionIDRefs.iterator(); 703 while (j.hasNext()) { 704 xml.append(((AssertionIDReference) j.next()). 705 toString(true, true)); 706 } 707 break; 708 case ASSERTION_ARTIFACT: 709 j = artifacts.iterator(); 710 while (j.hasNext()) { 711 xml.append(((AssertionArtifact) 712 j.next()).toString(includeNS, false)); 713 } 714 break; 715 default: 716 break; 717 } 718 719 xml.append("</").append(prefix).append("Request>"); 720 return xml.toString(); 721 } 722}