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: FSNameRegistrationResponse.java,v 1.3 2008/06/25 05:46:45 qcheng Exp $
026 *
027 * Portions Copyrighted 2014-2016 ForgeRock AS.
028 */
029
030package com.sun.identity.federation.message;
031
032import static org.forgerock.http.util.Uris.urlEncodeQueryParameterNameOrValue;
033import static org.forgerock.openam.utils.Time.*;
034
035import com.sun.identity.federation.common.FSUtils;
036import com.sun.identity.federation.common.IFSConstants;
037import com.sun.identity.federation.message.common.FSMsgException;
038import com.sun.identity.saml.common.SAMLConstants;
039import com.sun.identity.saml.common.SAMLException;
040import com.sun.identity.saml.common.SAMLResponderException;
041import com.sun.identity.saml.common.SAMLVersionMismatchException;
042import com.sun.identity.saml.protocol.AbstractResponse;
043import com.sun.identity.saml.protocol.Status;
044import com.sun.identity.saml.protocol.StatusCode;
045import com.sun.identity.saml.xmlsig.XMLSignatureManager;
046import com.sun.identity.shared.DateUtils;
047import com.sun.identity.shared.encode.Base64;
048import com.sun.identity.shared.xml.XMLUtils;
049import java.text.ParseException;
050import java.util.Date;
051import java.util.List;
052import javax.servlet.http.HttpServletRequest;
053import org.w3c.dom.Document;
054import org.w3c.dom.Element;
055import org.w3c.dom.Node;
056import org.w3c.dom.NodeList;
057
058/**
059 * This class has methods to create <code>NameRegistrationResponse</code>
060 * object.
061 *
062 * @supported.all.api
063 * @deprecated since 12.0.0
064 */
065@Deprecated
066
067public class FSNameRegistrationResponse extends AbstractResponse {
068    private String providerId = null;
069    private String relayState = "";
070    private Status status = null;
071    protected String xmlString        = null;
072    protected String signatureString        = null;
073    protected String id = null;
074    protected int minorVersion = 0;
075    
076    /**
077     * Default Constructor.
078     */
079    public FSNameRegistrationResponse() {
080        try {
081            setIssueInstant(newDate());
082            StatusCode statusCode = new StatusCode(IFSConstants.SAML_SUCCESS);
083            status = new Status(statusCode);
084        } catch(Exception e){
085            FSUtils.debug.error("FSNameRegistrationResponse.Constructor", e);
086        }
087    }
088    
089    /**
090     * Returns the value of <code>RelayState</code> attribute.
091     *
092     * @return the value of <code>RelayState</code> attribute.
093     * @see #setRelayState(String)
094     */
095    public String getRelayState(){
096        return relayState;
097    }
098    
099    /**
100     * Set the value of <code>RelayState</code> attribute.
101     *
102     * @param relayState the value of <code>RelayState</code> attribute.
103     * @see #getRelayState()
104     */
105    public void setRelayState(String relayState){
106        this.relayState = relayState;
107    }
108    
109    /**
110     * Returns the value of <code>id</code> attribute.
111     *
112     * @return the value of <code>id</code> attribute.
113     * @see #setID(String)
114     */
115    
116    public String getID(){
117        return id;
118    }
119    
120    /**
121     * Sets the value of <code>id</code> attribute.
122     *
123     * @param id the value of <code>id</code> attribute.
124     * @see #getID()
125     */
126    public void setID(String id){
127        this.id = id;
128    }
129    
130    /**
131     * Returns the value of <code>ProviderID</code> attribute.
132     *
133     * @return the value of <code>ProviderID</code> attribute.
134     * @see #setProviderId(String).
135     */
136    public String getProviderId(){
137        return providerId;
138    }
139    
140    /**
141     * Sets the value of providerID attribute.
142     *
143     * @param providerId the value of providerID attribute.
144     * @see #getProviderId()
145     */
146    public void setProviderId(String providerId){
147        this.providerId = providerId;
148    }
149    
150    /**
151     * Returns signed <code>XML</code> representation of this
152     * object.
153     *
154     * @return xmlString signed <code>XML</code> representation of this
155     *         object.
156     */
157    public String getSignedXMLString(){
158        return xmlString;
159    }
160    
161    /**
162     * Returns the signed <code>NameRegistrationResponse</code> string.
163     *
164     * @return signatureString the signed <code>NameRegistrationResponse</code>
165     *         string.
166     */
167    public String getSignatureString(){
168        return signatureString;
169    }
170    
171    /**
172     * Constructor creates the <code>FSNameRegistrationResponse</code> object.
173     *
174     * @param responseID the value of <code>ResponseID</code> attribute.
175     * @param inResponseTo the value of <code>InResponseTo</code> attribute.
176     * @param status the <code>Status</code> object.
177     * @param providerId the value of <code>ProviderID</code> attribute.
178     * @param relayState the value of <code>RelayState</code> attribute.
179     * @throws FSMsgException if there is an error creating this object.
180     */
181    public FSNameRegistrationResponse(String responseID, String inResponseTo,
182            Status status, String providerId,
183            String relayState) throws FSMsgException {
184        if ((responseID == null) || (responseID.length() == 0)) {
185            this.responseID = FSUtils.generateID();
186            if (this.responseID == null) {
187                throw new FSMsgException("errorGenerateID",null);
188            }
189        } else {
190            this.responseID = responseID;
191        }
192        if (inResponseTo == null) {
193            FSUtils.debug.message("Response: inResponseTo is null.");
194            throw new FSMsgException("nullInput",null);
195        }
196        this.inResponseTo = inResponseTo;
197        if (status == null) {
198            FSUtils.debug.message("Response: missing <Status>.");
199            throw new FSMsgException("missingElement",null);
200        }
201        this.status = status;
202        this.providerId = providerId;
203        this.relayState = relayState;
204        setIssueInstant(newDate());
205    }
206    
207    /**
208     * Constructor creates the <code>FSNameRegistrationResponse</code> object
209     * from Document Element.
210     *
211     * @param root the Document Element objec.t
212     * @throws FSMsgException if there is an error creating this object.
213     * @throws SAMLException if there is an error creating this object.
214     */
215    public FSNameRegistrationResponse(Element root) throws
216            FSMsgException, SAMLException {
217        if (root == null) {
218            FSUtils.debug.message("FSNameRegistrationResponse.parseXML:" +
219                    " null input.");
220            throw new FSMsgException("nullInput",null);
221        }
222        String tag = null;
223        if (((tag = root.getLocalName()) == null) ||
224                (!tag.equals("RegisterNameIdentifierResponse"))) {
225            FSUtils.debug.error("FSNameRegistrationResponse.parseXML: wrong"+
226                    " input.");
227            throw new FSMsgException("wrongInput",null);
228        }
229        
230        id = root.getAttribute("id");
231        
232        // Attribute ResponseID
233        responseID = root.getAttribute("ResponseID");
234        if ((responseID == null) || (responseID.length() == 0)) {
235            FSUtils.debug.error("FSNameRegistrationResponse.parseXML: "
236                    + "Reponse doesn't have ResponseID.");
237            String[] args = { IFSConstants.RESPONSE_ID };
238            throw new FSMsgException("missingAttribute",args);
239        }
240        
241        parseMajorVersion(root.getAttribute("MajorVersion"));
242        parseMinorVersion(root.getAttribute("MinorVersion"));
243        
244        // Attribute InResponseTo
245        inResponseTo = root.getAttribute("InResponseTo");
246        if (inResponseTo == null) {
247            FSUtils.debug.error("FSNameRegistrationResponse.parseXML: "
248                    + "Response doesn't have InResponseTo.");
249            String[] args = { IFSConstants.IN_RESPONSE_TO };
250            throw new FSMsgException("missingAttribute",args);
251        }
252        // Attribute IssueInstant
253        String instantString = root.getAttribute("IssueInstant");
254        if ((instantString == null) || (instantString.length() == 0)) {
255            FSUtils.debug.error("FSNameRegistrationResponse(Element): " +
256                    "missing IssueInstant");
257            String[] args = { IFSConstants.ISSUE_INSTANT };
258            throw new FSMsgException("missingAttribute",args);
259        } else {
260            try {
261                issueInstant = DateUtils.stringToDate(instantString);
262            } catch (ParseException e) {
263                FSUtils.debug.error(
264                        "FSNameRegistrationResponse(Element):" +
265                        " could not parse IssueInstant:" , e);
266                throw new FSMsgException("wrongInput",null);
267            }
268        }
269        
270        NodeList nl = root.getChildNodes();
271        Node child;
272        String childName;
273        int length = nl.getLength();
274        for (int i = 0; i < length; i++) {
275            child = nl.item(i);
276            if ((childName = child.getLocalName()) != null) {
277                if (childName.equals("Status")) {
278                    if (status != null) {
279                        FSUtils.debug.error("FSNameRegistrationResponse: " +
280                                "included more than one <Status>");
281                        throw new FSMsgException("moreElement",null);
282                    }
283                    status = new Status((Element) child);
284                } else if (childName.equals(IFSConstants.SIGNATURE)) {
285                } else if (childName.equals("ProviderID")) {
286                    if (providerId != null) {
287                        FSUtils.debug.error("FSNameRegistrationResponse:" +
288                                " included more than one providerId");
289                        throw new FSMsgException("moreElement",null);
290                    }
291                    providerId = XMLUtils.getElementValue((Element) child);
292                } else if (childName.equals("RelayState")) {
293                    relayState = XMLUtils.getElementValue((Element) child);
294                }else {
295                    FSUtils.debug.error("FSNameRegistrationResponse: " +
296                            "included wrong element:" + childName);
297                    throw new FSMsgException("wrongInput",null);
298                }
299            } // end if childName != null
300        } // end for loop
301        
302        if (status == null) {
303            FSUtils.debug.message(
304                    "FSNameRegistrationResponse: missing element <Status>.");
305            throw new FSMsgException("oneElement",null);
306        }
307        
308        if (providerId == null) {
309            FSUtils.debug.message(
310                    "FSNameRegistrationResponse: missing element providerId.");
311            throw new FSMsgException("oneElement",null);
312        }
313        
314        //check for signature
315        List signs = XMLUtils.getElementsByTagNameNS1(root,
316                SAMLConstants.XMLSIG_NAMESPACE_URI,
317                SAMLConstants.XMLSIG_ELEMENT_NAME);
318        int signsSize = signs.size();
319        if (signsSize == 1) {
320            Element elem = (Element)signs.get(0);
321            setSignature(elem);
322            xmlString = XMLUtils.print(root);
323            signed = true;
324        } else if (signsSize != 0) {
325            FSUtils.debug.error("FSNameRegistrationResponse(Element): " +
326                    "included more than one Signature element.");
327            throw new FSMsgException("moreElement",null);
328        }
329    }
330    
331    /**
332     * Returns the <code>MinorVersion</code>.
333     *
334     * @return the <code>MinorVersion</code>.
335     * @see #setMinorVersion(int)
336     */
337    public int getMinorVersion() {
338        return minorVersion;
339    }
340    
341    /**
342     * Sets the <code>MinorVersion</code>.
343     *
344     * @param version the <code>MinorVersion</code>.
345     * @see #getMinorVersion()
346     */
347    
348    public void setMinorVersion(int version) {
349        minorVersion = version;
350    }
351    
352    /**
353     * Returns the Response <code>Status</code>.
354     *
355     * @return the Response <code>Status</code>.
356     * @see #setStatus(Status)
357     */
358    public Status getStatus() {
359        return status;
360    }
361    
362    
363    /**
364     * Sets the Response <code>Status</code>.
365     *
366     * @param status the Response <code>Status</code object.
367     * @see #getStatus
368     */
369    public void setStatus(Status status) {
370        this.status=status;
371    }
372    
373    /**
374     * Sets the <code>MajorVersion</code> by parsing the version string.
375     *
376     * @param majorVer a String representing the <code>MajorVersion</code> to
377     *        be set.
378     * @throws FSMsgException on error.
379     * @throws SAMLException when the version mismatchs.
380     */
381    private void parseMajorVersion(
382            String majorVer
383            ) throws FSMsgException, SAMLException {
384        try {
385            majorVersion = Integer.parseInt(majorVer);
386        } catch (NumberFormatException e) {
387            FSUtils.debug.error("Response(Element): invalid MajorVersion", e);
388            throw new FSMsgException("wrongInput",null);
389        }
390        
391        if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) {
392            if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) {
393                if (FSUtils.debug.messageEnabled()) {
394                    FSUtils.debug.message("Response(Element):MajorVersion of"
395                            + " the Response is too high.");
396                }
397                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
398                        "responseVersionTooHigh",null);
399            } else {
400                if (FSUtils.debug.messageEnabled()) {
401                    FSUtils.debug.message("Response(Element):MajorVersion of"
402                            + " the Response is too low.");
403                }
404                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
405                        "responseVersionTooLow",null);
406            }
407        }
408    }
409    
410    /**
411     * Sets the <code>MinorVersion</code> by parsing the version string.
412     *
413     * @param minorVer a String representing the <code>MinorVersion</code> to
414     *        be set.
415     * @throws SAMLException when the version mismatchs.
416     */
417    private void parseMinorVersion(String minorVer) throws FSMsgException {
418        try {
419            minorVersion = Integer.parseInt(minorVer);
420        } catch (NumberFormatException e) {
421            if (FSUtils.debug.messageEnabled()) {
422                FSUtils.debug.message(
423                        "FSRegisResp(Element): "
424                        + "invalid MinorVersion", e);
425            }
426            throw new FSMsgException("wrongInput",null);
427        }
428        
429        if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
430            FSUtils.debug.error("FSRegisResp(Element):MinorVersion of"
431                    + " the Response is too high.");
432            throw new FSMsgException("responseVersionTooHigh",null);
433        } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
434            FSUtils.debug.error("FSRegisResp(Element):MinorVersion of"
435                    + " the Response is too low.");
436            throw new FSMsgException("responseVersionTooLow",null);
437        }
438        
439    }
440    
441    /**
442     * Returns the <code>FSNameRegistrationResponse</code> object.
443     *
444     * @param xml the XML string to be parsed.
445     * @return <code>FSNameRegistrationResponsee</code> object created from
446     *         the XML string.
447     * @throws FSMsgException if there is error creating the object.
448     */
449    public static FSNameRegistrationResponse parseXML(String xml)
450    throws FSMsgException {
451        try{
452            Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug);
453            Element root = doc.getDocumentElement();
454            return new FSNameRegistrationResponse(root);
455        }catch(SAMLException ex){
456            if (FSUtils.debug.messageEnabled()) {
457                FSUtils.debug.message("FSNameRegistrationResponse.parseXML: "
458                        + "Error while parsing input xml string");
459            }
460            throw new FSMsgException("parseError", null, ex);
461        }
462        
463    }
464    
465    /**
466     * Returns the string representation of this object.
467     * This method translates the response to an XML string.
468     *
469     * @return An XML String representing the Response.
470     * @throws FSMsgException on error.
471     */
472    public String toXMLString()  throws FSMsgException {
473        return this.toXMLString(true, true);
474    }
475    
476    /**
477     * Returns a String representation of the Logout Response.
478     *
479     * @param includeNS : Determines whether or not the namespace qualifier
480     *        is prepended to the Element when converted
481     * @param declareNS : Determines whether or not the namespace is declared
482     *        within the Element.
483     * @return a string containing the valid XML for this element
484     * @throws FSMsgException if there is an error converting
485     *         this object to a string.
486     */
487    public String toXMLString(boolean includeNS, boolean declareNS)
488    throws FSMsgException {
489        return toXMLString(includeNS, declareNS, false);
490    }
491    
492    /**
493     * Returns a String representation of the Logout Response.
494     *
495     * @param includeNS Determines whether or not the namespace qualifier
496     *        is prepended to the Element when converted
497     * @param declareNS Determines whether or not the namespace is declared
498     *        within the Element.
499     * @param includeHeader Determines whether the output include the xml
500     *        declaration header.
501     * @return a string containing the valid XML for this element
502     * @throws FSMsgException if there is an error converting
503     *         this object to a string.
504     */
505    public String toXMLString(boolean includeNS, boolean declareNS,
506            boolean includeHeader) throws FSMsgException {
507        StringBuffer xml = new StringBuffer(300);
508        if (includeHeader) {
509            xml.append("<?xml version=\"1.0\" encoding=\"").
510                    append(SAMLConstants.DEFAULT_ENCODING).append("\" ?>\n");
511        }
512        String prefixLIB = "";
513        String uriLIB = "";
514        if (includeNS) {
515            prefixLIB = IFSConstants.LIB_PREFIX;
516        }
517        
518        if (declareNS) {
519            if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
520                uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING;
521            } else {
522                uriLIB = IFSConstants.LIB_NAMESPACE_STRING;
523            }
524        }
525        
526        String instantString = DateUtils.toUTCDateFormat(issueInstant);
527        
528        if ((providerId == null) || (providerId.length() == 0)){
529            FSUtils.debug.error("FSNameRegistrationResponse.toXMLString: "
530                    + "providerId is null in the response with responseId:"
531                    + responseID);
532            throw new FSMsgException("nullProviderID",null);
533        }
534        
535        if ((responseID != null) && (inResponseTo != null)){
536            xml.append("<").append(prefixLIB).
537                    append("RegisterNameIdentifierResponse").append(uriLIB);
538            if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION &&
539                    id != null && !(id.length() == 0)) {
540                xml.append(" id=\"").append(id).append("\" ");
541            }
542            xml.append(" ResponseID=\"").append(responseID).append("\" ").
543                    append(" InResponseTo=\"").append(inResponseTo).
544                    append("\" ").
545                    append(" MajorVersion=\"").append(majorVersion).
546                    append("\" ").
547                    append(" MinorVersion=\"").append(minorVersion).
548                    append("\" ").
549                    append(" IssueInstant=\"").append(instantString).
550                    append("\" ").
551                    append(">");
552        }
553        
554        if (signed) {
555            if (signatureString != null) {
556                xml.append(signatureString);
557            } else if (signature != null) {
558                signatureString = XMLUtils.print(signature);
559                xml.append(signatureString);
560            }
561        }
562        
563        if (providerId != null) {
564            xml.append("<").append(prefixLIB).append("ProviderID").append(">").
565                    append(providerId).
566                    append("</").append(prefixLIB).append("ProviderID").
567                    append(">");
568        }
569        
570        if (status != null) {
571            xml.append(status.toString(includeNS, true));
572        }
573        
574        if (relayState != null) {
575            xml.append("<").append(prefixLIB).append("RelayState").
576                    append(">").append(relayState).
577                    append("</").append(prefixLIB).
578                    append("RelayState").append(">");
579        }
580        
581        xml.append("</").append(prefixLIB).
582                append("RegisterNameIdentifierResponse>");
583        return xml.toString();
584    }
585    
586    /**
587     * Returns <code>FSNameRegistrationResponse</code> object. The object
588     * is created by parsing an Base64 encode Name Registration Response
589     * string.
590     *
591     * @param encodedRes the encoded response string
592     * @throws FSMsgException if there is an error
593     *         creating this object.
594     * @throws SAMLException if there is an error
595     *         creating this object.
596     */
597    public static FSNameRegistrationResponse parseBASE64EncodedString(
598            String encodedRes) throws FSMsgException, SAMLException {
599        if (encodedRes != null){
600            String decodedNameRegRes = new String(Base64.decode(encodedRes));
601            if (FSUtils.debug.messageEnabled()) {
602                FSUtils.debug.message("FSNameRegistrationResponse."
603                        + "parseBASE64EncodedString: decoded input string: "
604                        + decodedNameRegRes);
605            }
606            return parseXML(decodedNameRegRes);
607        } else{
608            if (FSUtils.debug.messageEnabled()) {
609                FSUtils.debug.message(
610                        "FSNameRegistrationResponse.parseBASE64EncodedString"
611                        + ": null String passed in as argument.");
612            }
613            throw new FSMsgException("nullInput",null);
614        }
615    }
616    
617    /**
618     * Returns a Base64 Encoded String.
619     *
620     * @return a Base64 Encoded String.
621     * @throws FSMsgException if there is an error encoding
622     *         the string.
623     */
624    public String toBASE64EncodedString() throws FSMsgException {
625        if ((responseID == null) || (responseID.length() == 0)){
626            responseID = FSUtils.generateID();
627            if (responseID == null) {
628                FSUtils.debug.error(
629                        "FSNameRegistrationResponse.toBASE64EncodedString: "
630                        + "couldn't generate ResponseID.");
631                throw new FSMsgException("errorGenerateID",null);
632            }
633        }
634        return Base64.encode(this.toXMLString().getBytes());
635    }
636    
637    /**
638     * Signs the Name Registration Response.
639     *
640     * @param certAlias the Certificate Alias.
641     * @throws SAMLException if this object cannot be signed.
642     */
643    public void signXML(String certAlias) throws SAMLException {
644        FSUtils.debug.message("FSNameRegistrationResponse.signXML: Called");
645        if (signed) {
646            if (FSUtils.debug.messageEnabled()) {
647                FSUtils.debug.message("FSNameRegistrationResponse.signXML: "
648                        + "the assertion is already signed.");
649            }
650            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
651                    "alreadySigned",null);
652        }
653        if (certAlias == null || certAlias.length() == 0) {
654            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
655                    "cannotFindCertAlias",null);
656        }
657        try{
658            XMLSignatureManager manager = XMLSignatureManager.getInstance();
659            if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
660                signatureString = manager.signXML(this.toXMLString(true, true),
661                        certAlias, IFSConstants.DEF_SIG_ALGO, IFSConstants.ID,
662                        this.id, false);
663            } else if (minorVersion ==
664                    IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
665                signatureString = manager.signXML(this.toXMLString(true, true),
666                        certAlias, IFSConstants.DEF_SIG_ALGO,
667                        IFSConstants.RESPONSE_ID,
668                        this.getResponseID(), false);
669            } else {
670                if (FSUtils.debug.messageEnabled()) {
671                    FSUtils.debug.message("invalid minor version.");
672                }
673            }
674            signature =
675                    XMLUtils.toDOMDocument(signatureString, FSUtils.debug)
676                    .getDocumentElement();
677            
678            signed = true;
679            xmlString = this.toXMLString(true, true);
680        }catch(Exception e){
681            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
682                                             "signError",null);
683        }
684    }
685    
686    /**
687     * Unsupported operation.
688     */
689    public void signXML() throws SAMLException {
690        throw new SAMLException(FSUtils.BUNDLE_NAME,
691                               "unsupportedOperation",null);
692    }
693    
694    /**
695     * Sets the Signature.
696     *
697     * @param elem the Document Element.
698     * @return true if success otherwise false.
699     */
700    public boolean setSignature(Element elem) {
701        signatureString = XMLUtils.print(elem);
702        return super.setSignature(elem);
703    }
704    
705    /**
706     * Returns an URL Encoded String.
707     *
708     * @return a url encoded query string.
709     * @throws FSMsgException if there is an error.
710     */
711    public String toURLEncodedQueryString() throws FSMsgException {
712        if ((providerId == null) || (providerId.length() == 0)){
713            FSUtils.debug.error("FSNameRegistrationResponse."
714                    + "toURLEncodedQueryString: providerId is null in "
715                    + "the response ");
716            throw new FSMsgException("nullProviderIdInRequest",null);
717        }
718        if ((responseID == null) || (responseID.length() == 0)){
719            responseID = FSUtils.generateID();
720            if (responseID == null) {
721                FSUtils.debug.error("FSNameRegistrationRequest."
722                        + "toURLEncodedQueryString: couldn't generate "
723                        + "responseID.");
724                throw new FSMsgException("errorGenerateID",null);
725            }
726        }
727        StringBuffer urlEncodedAuthnReq = new StringBuffer(300);
728        urlEncodedAuthnReq.append("ResponseID=").
729                append(urlEncodeQueryParameterNameOrValue(responseID)).
730                append(IFSConstants.AMPERSAND);
731        urlEncodedAuthnReq.append("MajorVersion=").
732                append(majorVersion).append(IFSConstants.AMPERSAND);
733        urlEncodedAuthnReq.append("MinorVersion=").
734                append(minorVersion).append(IFSConstants.AMPERSAND);
735        urlEncodedAuthnReq.append("InResponseTo=").
736                append(urlEncodeQueryParameterNameOrValue(inResponseTo)).
737                append(IFSConstants.AMPERSAND);
738        
739        if (issueInstant != null){
740            urlEncodedAuthnReq.append("IssueInstant=")
741            .append(urlEncodeQueryParameterNameOrValue(
742                    DateUtils.toUTCDateFormat(issueInstant)))
743                    .append(IFSConstants.AMPERSAND);
744        } else {
745            FSUtils.debug.error("FSNameRegistrationRequest."
746                    + "toURLEncodedQueryString: issueInstant missing");
747            String[] args = { IFSConstants.ISSUE_INSTANT };
748            throw new FSMsgException("missingAttribute",args);
749        }
750        if (providerId != null && !providerId.equals("")) {
751            urlEncodedAuthnReq.append("ProviderID=").
752                    append(urlEncodeQueryParameterNameOrValue(providerId)).
753                    append(IFSConstants.AMPERSAND);
754        }
755        
756        if (relayState != null && relayState.length() > 0) {
757            urlEncodedAuthnReq.append("RelayState=").
758                    append(urlEncodeQueryParameterNameOrValue(relayState)).
759                    append(IFSConstants.AMPERSAND);
760        }
761        
762        if (status != null) {
763            urlEncodedAuthnReq.append("Value=");
764            urlEncodedAuthnReq.append(
765                    urlEncodeQueryParameterNameOrValue(status.getStatusCode().getValue())).
766                    append(IFSConstants.AMPERSAND);
767        }
768        
769        return urlEncodedAuthnReq.toString();
770    }
771    
772    
773    /**
774     * Returns <code>FSNameRegistrationLogoutResponse</code> object. The
775     * object is creating by parsing the <code>HttpServletRequest</code>
776     * object.
777     *
778     * @param request the <code>HttpServletRequest</code> object.
779     * @throws FSMsgException if there is an error
780     *         creating this object.
781     */
782    public static FSNameRegistrationResponse parseURLEncodedRequest(
783            HttpServletRequest request) throws FSMsgException, SAMLException {
784        FSNameRegistrationResponse retNameRegistrationResponse =
785                new FSNameRegistrationResponse();
786        try {
787            FSUtils.debug.message("checking minor version");
788            retNameRegistrationResponse.majorVersion =
789                    Integer.parseInt(request.getParameter("MajorVersion"));
790            retNameRegistrationResponse.minorVersion =
791                    Integer.parseInt(request.getParameter("MinorVersion"));
792        } catch(NumberFormatException ex){
793            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
794                    "EncodedRequest: version parsing error:" + ex);
795            throw new FSMsgException("invalidNumber",null);
796        }
797        
798        if (request.getParameter("ResponseID")!= null) {
799            retNameRegistrationResponse.responseID =
800                    request.getParameter("ResponseID");
801        } else {
802            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
803                    "EncodedRequest: Response ID is null" );
804            String[] args = { IFSConstants.RESPONSE_ID };
805            throw new FSMsgException("missingAttribute",args);
806        }
807        
808        String instantString = request.getParameter("IssueInstant");
809        if (instantString == null || instantString.length() == 0) {
810            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
811                    "EncodedRequest: Issue Instant is null" );
812            String[] args = { IFSConstants.ISSUE_INSTANT };
813            throw new FSMsgException("missingAttribute",args);
814        }
815        try{
816            retNameRegistrationResponse.issueInstant =
817                    DateUtils.stringToDate(instantString);
818        } catch (ParseException e){
819            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
820                    "EncodedRequest: Can not parse Issue Instant", e);
821            throw new FSMsgException("parseError",null);
822        }
823        if (request.getParameter("ProviderID")!= null){
824            retNameRegistrationResponse.providerId =
825                    request.getParameter("ProviderID");
826        } else {
827            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
828                    "EncodedRequest: Provider ID is null " );
829            throw new FSMsgException("missingElement",null);
830        }
831        
832        if (request.getParameter("RelayState")!= null){
833            retNameRegistrationResponse.relayState =
834                    request.getParameter("RelayState");
835        }
836        if (request.getParameter("InResponseTo")!= null){
837            retNameRegistrationResponse.inResponseTo =
838                    request.getParameter("InResponseTo");
839        }
840        
841        if (request.getParameter("Value") != null){
842            FSUtils.debug.message("Status : " + request.getParameter("Value"));
843            StatusCode statusCode =
844                    new StatusCode(request.getParameter("Value"));
845            retNameRegistrationResponse.status = new Status(statusCode);
846        } else {
847            FSUtils.debug.error("FSNameRegistrationResponse.parseURL" +
848                    "EncodedRequest: Status Value is  null " );
849            throw new FSMsgException("missingElement",null);
850        }
851        
852        FSUtils.debug.message("Returning registration response Object");
853        return retNameRegistrationResponse;
854    }
855}