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