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: FSAssertion.java,v 1.2 2008/06/25 05:46:43 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.federation.message;
031
032import com.sun.identity.federation.common.FSUtils;
033import com.sun.identity.federation.common.IFSConstants;
034import com.sun.identity.federation.message.common.FSMsgException;
035import com.sun.identity.saml.assertion.Advice;
036import com.sun.identity.saml.assertion.Assertion;
037import com.sun.identity.saml.assertion.AttributeStatement;
038import com.sun.identity.saml.assertion.AuthorizationDecisionStatement;
039import com.sun.identity.saml.assertion.Conditions;
040import com.sun.identity.saml.assertion.Statement;
041import com.sun.identity.saml.common.SAMLConstants;
042import com.sun.identity.saml.common.SAMLException;
043import com.sun.identity.saml.common.SAMLResponderException;
044import com.sun.identity.saml.common.SAMLVersionMismatchException;
045import com.sun.identity.saml.xmlsig.XMLSignatureManager;
046import com.sun.identity.liberty.ws.security.SecurityAssertion;
047import com.sun.identity.shared.DateUtils;
048import com.sun.identity.shared.xml.XMLUtils;
049import java.text.ParseException;
050import java.util.ArrayList;
051import java.util.Date;
052import java.util.Iterator;
053import java.util.List;
054import java.util.Set;
055import org.w3c.dom.Element;
056import org.w3c.dom.Node;
057import org.w3c.dom.NodeList;
058
059/**
060 * The class <code>FSAssertion</code> creates and parses Liberty
061 * <code>Assertion</code> during the Single Sign-On process.
062 * This class extends from SAML Assertion.
063 *
064 * @supported.all.api
065 */
066public class FSAssertion extends Assertion {
067    
068    /**
069     * The Document Element of this object.
070     */
071    private Element domElement;
072    
073    /**
074     * The <code>SAMLConstants</code> object.
075     */
076    static SAMLConstants sc;
077    
078    /**
079     * The value of the <code>id</code> attribute in the <code>Assertion</code>.
080     */
081    protected String id;
082    
083    /**
084     * The value of the <code>MinorVersion</Version> attribute in
085     * the <code>Assertion</code>.
086     */
087    protected int minorVersion = IFSConstants.FF_11_ASSERTION_MINOR_VERSION;
088    
089    /**
090     * List of Security <code>Assertions</code>.
091     */
092    private List securityAssertions;
093    
094    /**
095     * The value of the <code>InResponseTo</code> attribute in the
096     * <code>Assertion</code>.
097     */
098    protected String inResponseTo ;
099    
100    /**
101     * Constructor to create an <code>FSAssertion</code> object
102     * from the Document Element.
103     *
104     * @param assertionElement the <code>Assertion</code> Document Element.
105     * @throws FSMsgException if the document element is null
106     *         or cannot be retrieved.
107     * @throws SAMLException if the SAML Assertion version is
108     *         incorrect
109     */
110    public FSAssertion(Element assertionElement )
111    throws FSMsgException, SAMLException {
112        FSUtils.debug.message("FSAssertion(Element):  Called");
113        Element elt = (Element) assertionElement;
114        String eltName = elt.getLocalName();
115        if (eltName == null)  {
116            if (FSUtils.debug.messageEnabled()) {
117                FSUtils.debug.message("FSAssertion: local name missing");
118            }
119            throw new FSMsgException("nullInput", null) ;
120        }
121        if (!(eltName.equals(IFSConstants.ASSERTION)))  {
122            if (FSUtils.debug.messageEnabled()) {
123                FSUtils.debug.message("FSAssertion: invalid root element");
124            }
125            String[] args = { eltName };
126            throw new FSMsgException("invalidElement" , args) ;
127        }
128        domElement = assertionElement;
129        id = elt.getAttribute(IFSConstants.ID);
130        String read = elt.getAttribute(IFSConstants.MAJOR_VERSION);
131        if ((read == null) || (read.length() == 0)) {
132            if (FSUtils.debug.messageEnabled()) {
133                FSUtils.debug.message("FSAssertion: MajorVersion missing");
134            }
135            String[] args = { "MajorVersion" };
136            throw new FSMsgException("missingAttribute", args);
137        } else  {
138            int ver = 0;
139            try {
140                ver = Integer.parseInt(read);
141            } catch ( NumberFormatException ne ) {
142                FSUtils.debug.error("FSAssertion: invalid integer " +
143                        "in MajorVersion", ne);
144                throw new FSMsgException("invalidNumber",null);
145            }
146            if (ver != sc.ASSERTION_MAJOR_VERSION) {
147                if(ver < sc.ASSERTION_MAJOR_VERSION) {
148                    FSUtils.debug.error("FSAssertion: MajorVersion too low");
149                    throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
150                            "assertionVersionTooLow",null);
151                } else if (ver > sc.ASSERTION_MAJOR_VERSION) {
152                    FSUtils.debug.error("FSAssertion: MajorVersion too high");
153                    throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
154                            "assertionVersionTooHigh",null);
155                }
156            }
157        }
158        read = elt.getAttribute(IFSConstants.MINOR_VERSION);
159        if ((read == null) || (read.length() == 0)) {
160            FSUtils.debug.error("FSAssertion: MinorVersion missing");
161            String[] args = { "MinorVersion" };
162            throw new FSMsgException("missingAttribute",args);
163        } else  {
164            try {
165                minorVersion = Integer.parseInt(read);
166            } catch ( NumberFormatException ne ) {
167                FSUtils.debug.error(
168                        "FSAssertion: invalid integer in MinorVersion", ne);
169                throw new FSMsgException("invalidNumber",null);
170            }
171            if (minorVersion < IFSConstants.FF_11_ASSERTION_MINOR_VERSION) {
172                FSUtils.debug.error("FSAssertion: MinorVersion too low");
173                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
174                        "assertionVersionTooLow",null);
175            } else if (minorVersion >
176                    IFSConstants.FF_12_POST_ASSERTION_MINOR_VERSION) {
177                FSUtils.debug.error("FSAssertion: MinorVersion too high");
178                throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME,
179                        "assertionMinorVersionTooHigh",null);
180            }
181        }
182        read = elt.getAttribute(IFSConstants.ASSERTION_ID);
183        if ((read == null) || (read.length() == 0)) {
184            if (FSUtils.debug.messageEnabled()) {
185                FSUtils.debug.message("FSAssertion: AssertionID missing");
186            }
187            String[] args = { IFSConstants.ASSERTION_ID };
188            throw new FSMsgException("missingAttribute",args);
189        } else {
190            setAssertionID(read);
191        }
192        read = elt.getAttribute(IFSConstants.ISSUER);
193        if ((read == null) || (read.length() == 0)) {
194            if (FSUtils.debug.messageEnabled()) {
195                FSUtils.debug.message("FSAssertion: Issuer missing");
196            }
197            String[] args = { IFSConstants.ISSUER };
198            throw new FSMsgException("missingAttribute",args);
199        } else {
200            setIssuer(read);
201        }
202        read = elt.getAttribute(IFSConstants.IN_RESPONSE_TO);
203        if ((read == null) || (read.length() == 0)) {
204            if (FSUtils.debug.messageEnabled())  {
205                FSUtils.debug.message("FSAssertion: InResponseTo missing");
206            }
207            String[] args = { IFSConstants.IN_RESPONSE_TO };
208            throw new FSMsgException("missingAttribute",args);
209        } else  {
210            inResponseTo = read;
211        }
212        read = elt.getAttribute(IFSConstants.ISSUE_INSTANT);
213        if ((read == null) || (read.length() == 0)) {
214            if (FSUtils.debug.messageEnabled())  {
215                FSUtils.debug.message("FSAssertion: IssueInstant missing");
216            }
217            String[] args = { IFSConstants.ISSUE_INSTANT };
218            throw new FSMsgException("missingAttribute",args);
219        } else  {
220            try {
221                setIssueInstant(DateUtils.stringToDate(read));
222            } catch (ParseException pe) {
223                FSUtils.debug.message(
224                        "FSAssertion: could not parse IssueInstant", pe);
225                throw new FSMsgException("wrongInput",null);
226            }
227        }
228        boolean statementFound = false;
229        NodeList nl = assertionElement.getChildNodes();
230        int length = nl.getLength();
231        for (int n=0; n<length; n++) {
232            Node child = (Node)nl.item(n);
233            if (child.getNodeType() != Node.ELEMENT_NODE) continue;
234            String childName = child.getLocalName();
235            if (childName.equals(IFSConstants.CONDITIONS)){
236                setConditions(new Conditions((Element)child));
237            } else if (childName.equals(IFSConstants.ADVICE)){
238                /**
239                 * The SAML Advice could not parse this advice as it does not
240                 * anything about Resource Access Statement. Hence commenting
241                 * the following and parsing in this assertion only. Currently
242                 * the FSAssertion does not have any advice element besides for
243                 * the credential.
244                 */
245                parseAdvice((Element)child);
246            } else if (childName.equals(IFSConstants.AUTHENTICATIONSTATEMENT)) {
247                addStatement(new FSAuthenticationStatement((Element)child));
248                statementFound=true;
249            } else if (childName.equals(IFSConstants.AUTHZDECISIONSTATEMENT)) {
250                addStatement(new AuthorizationDecisionStatement(
251                        (Element)child));
252                statementFound=true;
253            } else if (childName.equals(IFSConstants.ATTRIBUTESTATEMENT)) {
254                addStatement(new AttributeStatement((Element)child));
255                statementFound=true;
256            } else if (childName.equals(IFSConstants.SIGNATURE)) {
257                if (FSUtils.debug.messageEnabled()) {
258                    FSUtils.debug.message("FSAssertion: Signature found");
259                }
260            } else {
261                if (FSUtils.debug.messageEnabled()) {
262                    FSUtils.debug.message(
263                            "FSAssertion: invalid element in Assertion");
264                }
265                throw new FSMsgException("invalidElement", null);
266            }
267        }
268        //check for signature
269        List signs = XMLUtils.getElementsByTagNameNS1(assertionElement,
270                SAMLConstants.XMLSIG_NAMESPACE_URI,
271                SAMLConstants.XMLSIG_ELEMENT_NAME);
272        int signsSize = signs.size();
273        if (signsSize == 1) {
274            Element elem = (Element)signs.get(0);
275            setSignature(elem);
276            xmlString = XMLUtils.print(assertionElement);
277            signed = true;
278        } else if (signsSize != 0) {
279            if (FSUtils.debug.messageEnabled()) {
280                FSUtils.debug.message("FSAssertion(Element): included more than"
281                        + " one Signature element.");
282            }
283            throw new FSMsgException("moreElement", null);
284        }
285        //end check for signature
286        if (!statementFound) {
287            if (FSUtils.debug.messageEnabled()) {
288                FSUtils.debug.message("Assertion: mandatory statement missing");
289            }
290            throw new FSMsgException("missingStatement",null);
291        }
292        FSUtils.debug.message("FSAssertion(Element): leaving");
293    }
294    
295    /**
296     * Constructor to create <code>FSAssertion</code> object.
297     *
298     * @param assertionID the <code>AssertionID</code> element.
299     * @param issuer the <code>Issuer</code> element.
300     * @param issueInstant the <code>IssueInstant</code> element.
301     * @param statements the <code>Statement</code> elements.
302     *        List of statements that need to be added in assertion.
303     * @param inResponseTo value of <code>InResponseTo</code> attribute in the
304     *        assertion.
305     * @throws FSMsgException if the document element is null
306     *         or cannot be retrieved.
307     * @throws SAMLException if the SAML Assertion version is
308     *         incorrect.
309     */
310    public FSAssertion(String assertionID,String issuer,Date issueInstant,
311            Set statements,String inResponseTo)
312            throws FSMsgException, SAMLException {
313        super(assertionID, issuer, issueInstant, statements);
314        this.inResponseTo = inResponseTo;
315    }
316    
317    /**
318     * Constructor to create <code>FSAssertion</code> object.
319     *
320     * @param assertionID the <code>AssertionID</code> element.
321     * @param issuer the <code>Issuer</code> element.
322     * @param issueInstant the <code>IssueInstant</code> element.
323     * @param conditions the <code>Conditions</code> object.
324     * @param statements the <code>Statement</code> elements.
325     *        List of statements that need to be added in assertion.
326     * @param inResponseTo value of <code>InResponseTo</code> attribute in
327     *        the assertion.
328     * @throws FSMsgException if the document element is null
329     *         or cannot be retrieved.
330     * @throws SAMLException if the SAML Assertion version is
331     *         incorrect.
332     */
333    public FSAssertion(String assertionID,String issuer,Date issueInstant,
334            Conditions conditions,Set statements,String inResponseTo)
335            throws FSMsgException, SAMLException {
336        super(assertionID, issuer, issueInstant, conditions, statements);
337        this.inResponseTo = inResponseTo;
338    }
339    
340    /**
341     * Constructor to create an <code>FSAssertion</code> object.
342     *
343     * @param assertionID the <code>AssertionID</code> element.
344     * @param issuer the <code>Issuer</code> element.
345     * @param issueInstant the <code>IssueInstant</code> element.
346     * @param conditions the <code>Conditions</code> object.
347     * @param advice the <code>Advice</code> object.
348     * @param statements the <code>Statement</code> elements.
349     *        List of statements that need to be added in assertion.
350     * @param inResponseTo value of <code>InResponseTo</code> attribute
351     *        in the assertion.
352     * @throws FSMsgException if the document element is null
353     *         or cannot be retrieved.
354     * @throws SAMLException if the SAML Assertion version is
355     *         incorrect.
356     */
357    public FSAssertion(String assertionID,String issuer,Date issueInstant,
358            Conditions conditions,Advice advice,Set statements,
359            String inResponseTo)
360            throws FSMsgException, SAMLException {
361        super(assertionID, issuer, issueInstant,conditions, advice, statements);
362        this.inResponseTo = inResponseTo;
363    }
364    
365    /**
366     * Returns value of <code>id</code> attribute.
367     *
368     * @return value of <code>id</code> attribute.
369     * @see #setID(String)
370     */
371    public String getID(){
372        return id;
373    }
374    
375    /**
376     * Sets  value of <code>id<code> attribute.
377     *
378     * @param id value of <code>id</code> attribute.
379     * @see #getID
380     */
381    public void setID(String id){
382        this.id = id;
383    }
384    
385    /**
386     * Returns the <code>MinorVersion</code> attribute.
387     *
388     * @return the <code>MinorVersion</code> attribute.
389     * @see #setMinorVersion(int)
390     */
391    public int getMinorVersion() {
392        return minorVersion;
393    }
394    
395    /**
396     * Sets the <code>MinorVersion</code> attribute.
397     *
398     * @param version the <code>MinorVersion</code> attribute.
399     * @see #getMinorVersion
400     */
401    public void setMinorVersion(int version) {
402        minorVersion = version;
403    }
404    
405    /**
406     * Returns the Document Element for this object.
407     *
408     * @return the Document Element for this object.
409     */
410    public Element getDOMElement() {
411        return domElement;
412    }
413    
414    /**
415     * Returns the value of <code>InResponseTo</code> attribute.
416     *
417     * @return the value of <code>InResponseTo</code> attribute.
418     * @see #setInResponseTo(String)
419     */
420    public String getInResponseTo() {
421        return inResponseTo;
422    }
423    
424    /**
425     * Sets the value of <code>InResponseTo</code> attribute.
426     *
427     * @param inResponseTo value of <code>InResponseTo</code> attribute.
428     * @see #getInResponseTo
429     */
430    public void setInResponseTo(String inResponseTo) {
431        this.inResponseTo = inResponseTo;
432    }
433    
434    /**
435     * Returns Signed XML String.
436     *
437     * @return Signed XML String.
438     */
439    public String getSignedXMLString(){
440        return xmlString;
441    }
442    
443    /**
444     * Returns the <code>Signature</code> string.
445     *
446     * @return the <code>Signature</code> string.
447     */
448    public String getSignatureString(){
449        return signatureString;
450    }
451    
452    /**
453     * Checks validity of time in the assertion.
454     *
455     * @return true if time is valid otherwise false.
456     */
457    public boolean isTimeValid() {
458        boolean isTimeValid = true;
459        Conditions conditions = getConditions();
460        if (conditions != null)  {
461            isTimeValid = conditions.checkDateValidity(
462                    System.currentTimeMillis());
463        }
464        return isTimeValid;
465    }
466    
467    /**
468     * Adds the <code>Statement</code> object to the
469     * Statment's object Set.
470     *
471     * @param statement the <code>Statement</code> object.
472     * @return false if statement is null else true.
473     */
474    public boolean addStatement(Statement statement) {
475        boolean addedStmt = false;
476        if (statement != null) {
477            super.addStatement(statement);
478            addedStmt = true;
479        }
480        return addedStmt;
481    }
482    
483    /**
484     * Returns a <code>XML</code> String representation of this object.
485     *
486     * @return a String representation of this Object.
487     * @throws FSMsgException if there is an error creating
488     *         the <code>XML</code> string.
489     */
490    
491    public String toXMLString() throws FSMsgException {
492        return this.toXMLString(true, true);
493    }
494    
495    /**
496     * Returns a <code>XML</code> String representation of this object.
497     *
498     * @param includeNS determines whether or not the namespace qualifier is
499     *                prepended to the Element when converted
500     * @param declareNS determines whether or not the namespace is declared
501     *                within the Element.
502     * @return a string containing the valid <code>XML</code> for this object.
503     * @throws FSMsgException if there is an error creating
504     *         the <code>XML</code> string.
505     */
506    
507    public java.lang.String toXMLString(boolean includeNS,boolean declareNS)
508    throws FSMsgException {
509        StringBuffer xml = new StringBuffer(3000);
510        String NS="";
511        String appendNS="";
512        String libNS="";
513        String libAppendNS="";
514        String uriXSI="";
515        if (declareNS) {
516            NS=sc.assertionDeclareStr;
517            if(minorVersion == IFSConstants.FF_12_POST_ASSERTION_MINOR_VERSION
518                    || minorVersion ==
519                    IFSConstants.FF_12_ART_ASSERTION_MINOR_VERSION) {
520                libNS = IFSConstants.LIB_12_NAMESPACE_STRING;
521            } else {
522                libNS = IFSConstants.LIB_NAMESPACE_STRING;
523            }
524            uriXSI = IFSConstants.XSI_NAMESPACE_STRING;
525        }
526        if (includeNS) {
527            appendNS= SAMLConstants.ASSERTION_PREFIX;
528            libAppendNS = IFSConstants.LIB_PREFIX;
529        }
530        String dateStr = null;
531        if (getIssueInstant() != null)  {
532            dateStr = DateUtils.toUTCDateFormat(getIssueInstant());
533        }
534        xml.append(IFSConstants.LEFT_ANGLE)
535        .append(appendNS).append(IFSConstants.ASSERTION)
536        .append(IFSConstants.SPACE)
537        .append(NS).append(IFSConstants.SPACE).append(uriXSI)
538        .append(IFSConstants.SPACE).append(libNS)
539        .append(IFSConstants.SPACE);
540        
541        if (minorVersion == IFSConstants.FF_11_ASSERTION_MINOR_VERSION &&
542                id != null && !(id.length() == 0)) {
543            xml.append(IFSConstants.SPACE).append(IFSConstants.ID)
544            .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
545            .append(id).append(IFSConstants.QUOTE)
546            .append(IFSConstants.SPACE);
547        }
548        xml.append(IFSConstants.MAJOR_VERSION)
549        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
550        .append(getMajorVersion()).append(IFSConstants.QUOTE)
551        .append(IFSConstants.SPACE).append(IFSConstants.MINOR_VERSION)
552        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
553        .append(minorVersion).append(IFSConstants.QUOTE)
554        .append(IFSConstants.SPACE).append(IFSConstants.ASSERTION_ID)
555        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
556        .append(getAssertionID()).append(IFSConstants.QUOTE)
557        .append(IFSConstants.SPACE).append(IFSConstants.ISSUER)
558        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
559        .append(getIssuer()).append(IFSConstants.QUOTE)
560        .append(IFSConstants.SPACE).append(IFSConstants.ISSUE_INSTANT)
561        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
562        .append(dateStr).append(IFSConstants.QUOTE)
563        .append(IFSConstants.SPACE).append(IFSConstants.IN_RESPONSE_TO)
564        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
565        .append(inResponseTo).append(IFSConstants.QUOTE)
566        .append(IFSConstants.SPACE)
567        .append(IFSConstants.XSI_TYPE)
568        .append(IFSConstants.EQUAL_TO).append(IFSConstants.QUOTE)
569        .append(libAppendNS)
570        .append(IFSConstants.ASSERTION_TYPE).append(IFSConstants.QUOTE)
571        .append(IFSConstants.RIGHT_ANGLE).append(sc.NL);
572        
573        if (getConditions() != null) {
574            xml.append(getConditions().toString(includeNS, false));
575        }
576        if (getAdvice() != null) {
577            xml.append(getAdvice().toString(includeNS, false));
578        }
579        
580        Iterator i = getStatement().iterator();
581        while (i.hasNext()) {
582            Statement st = (Statement)i.next();
583            if(st instanceof FSAuthenticationStatement){
584                xml.append(((FSAuthenticationStatement)st).toXMLString(
585                        includeNS, false));
586            } else if(st instanceof AttributeStatement) {
587                xml.append(((AttributeStatement)st).toString(includeNS, false));
588            }
589        }
590        if (signed) {
591            if (signatureString != null) {
592                xml.append(signatureString);
593            } else if (signature != null) {
594                signatureString = XMLUtils.print(signature);
595                xml.append(signatureString);
596            }
597        }
598        xml.append(IFSConstants.START_END_ELEMENT)
599        .append(appendNS).append(IFSConstants.ASSERTION)
600        .append(IFSConstants.RIGHT_ANGLE)
601        .append(IFSConstants.NL);
602        
603        return xml.toString();
604    }
605    
606    /**
607     * Signs the <code>Assertion</code>.
608     *
609     * @param certAlias the alias/name of the certificate.
610     * @throws SAMLException if <code>FSAssertion</code>
611     *            cannot be signed.
612     */
613    public void signXML(String certAlias) throws SAMLException {
614        FSUtils.debug.message("FSAssertion.signXML: Called");
615        if (signed) {
616            if (FSUtils.debug.messageEnabled()) {
617                FSUtils.debug.message("FSAssertion.signXML: the assertion is "
618                        + "already signed.");
619            }
620            throw new SAMLResponderException(
621                    FSUtils.BUNDLE_NAME,"alreadySigned",null);
622        }
623        if (certAlias == null || certAlias.length() == 0) {
624            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
625                    "cannotFindCertAlias",null);
626        }
627        
628        try {
629            XMLSignatureManager manager = XMLSignatureManager.getInstance();
630            if (minorVersion == IFSConstants.FF_11_ASSERTION_MINOR_VERSION) {
631                signatureString = manager.signXML(this.toXMLString(true, true),
632                        certAlias, (String) null,
633                        IFSConstants.ID, this.id,
634                        false);
635            } else if (minorVersion ==
636                    IFSConstants.FF_12_POST_ASSERTION_MINOR_VERSION
637                    || minorVersion ==
638                    IFSConstants.FF_12_ART_ASSERTION_MINOR_VERSION) {
639                signatureString =
640                        manager.signXML(this.toXMLString(true, true),
641                        certAlias, (String) null,
642                        IFSConstants.ASSERTION_ID,
643                        this.getAssertionID(), false);
644            } else {
645                if (FSUtils.debug.messageEnabled()) {
646                    FSUtils.debug.message("invalid minor version.");
647                }
648            }
649            signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug)
650            .getDocumentElement();
651            signed = true;
652            xmlString = this.toXMLString(true, true);
653        } catch(Exception e){
654            FSUtils.debug.message(" Exception :" + e.getMessage());
655            throw new SAMLResponderException(e);
656        }
657    }
658    
659    /**
660     * Sets the <code>Element's</code> signature.
661     *
662     * @param elem the <code>Element</code> object
663     * @return true if signature is set otherwise false
664     */
665    public boolean setSignature(Element elem) {
666        signatureString = XMLUtils.print(elem);
667        return super.setSignature(elem);
668    }
669    
670    /**
671     * Parses the advice element to extract the Security <code>Assertion</code>.
672     *
673     * @param element the <code>Advice</code> Element.
674     */
675    public void parseAdvice(Element element) {
676        NodeList nl = element.getChildNodes();
677        int length = nl.getLength();
678        for (int n=0; n<length; n++) {
679            Node child = (Node)nl.item(n);
680            if (child.getNodeType() != Node.ELEMENT_NODE) {
681                continue;
682            }
683            String childName = child.getLocalName();
684            if (childName.equals("Assertion")) {
685                try {
686                    if (securityAssertions == null) {
687                        securityAssertions = new ArrayList();
688                    }
689                    securityAssertions.add(
690                            new SecurityAssertion((Element)child));
691                } catch (Exception ex) {
692                    FSUtils.debug.error("FSAssertion.parseAdvice: Error in" +
693                            "parsing security assertion", ex);
694                }
695            }
696        }
697        if ((securityAssertions != null) && (!securityAssertions.isEmpty())) {
698            _advice = new Advice(null, securityAssertions, null);
699        }
700    }
701    
702    /**
703     * Returns the discovery service credentials from the boot strap.
704     *
705     * @return the discovery service credentials from the boot strap.
706     */
707    public List getDiscoveryCredential() {
708        return securityAssertions;
709    }
710}