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