/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: Subject.java,v 1.2 2008/06/25 05:47:33 qcheng Exp $ * */ package com.sun.identity.saml.assertion; import com.sun.identity.saml.common.SAMLUtilsCommon; import com.sun.identity.saml.common.SAMLConstants; import com.sun.identity.saml.common.SAMLException; import com.sun.identity.saml.common.SAMLRequesterException; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.Node; /** *The Subject element specifies one or more subjects. It contains *either or both of the following elements: *NameIdentifier *An identification of a subject by its name and security domain. *SubjectConfirmation *Information that allows the subject to be authenticated. * *If a Subject element contains more than one subject *specification, the issuer is asserting that the surrounding statement is *true for all of the subjects specified. For example, if both a *NameIdentifier and a SubjectConfirmation element *are present, the issuer is asserting that the statement is true of both *subjects being identified. A Subject element SHOULD NOT identify *more than one principal. *@supported.all.api */ public class Subject { static SAMLConstants sc; protected SubjectConfirmation _subjectConfirmation; protected NameIdentifier _nameIdentifier; /** *Default constructor */ protected Subject() {} /** * Constructs a Subject object from a NameIdentifier * object and a SubjectConfirmation object. * * @param nameIdentifier NameIdentifier object. * @param subjectConfirmation SubjectConfirmation object. * @exception SAMLException if it could not process the * Element properly, implying that there is an error in the * sender or in the element definition. */ public Subject(NameIdentifier nameIdentifier, SubjectConfirmation subjectConfirmation) throws SAMLException { if ((nameIdentifier == null) && (subjectConfirmation == null)) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message( "Subject: null NameIdentifier and SubjectConfirmation " + " specified"); } throw new SAMLRequesterException( SAMLUtilsCommon.bundle.getString("nullInput")) ; } if (nameIdentifier != null) { _nameIdentifier = nameIdentifier; } if (subjectConfirmation != null) { _subjectConfirmation = subjectConfirmation; } } /** * Checks for equality between this object and the Subject * passed down as parameter. If NameIdentifier is present, * checks for its equality by calling Nameidentifier.equals(). * if SubjectConfirmation is present calls * equals() method of SubjectConfirmation too * passing in the subject's SubjectConfirmation element. * * @param subject Subject to be checked. * @return true if this object and subject are equals. */ public boolean equals(Subject subject) { boolean nidEqual=false; boolean scEqual=false; if (subject != null) { // the ones passed as a parameter is not null NameIdentifier nid = subject.getNameIdentifier(); if (_nameIdentifier != null) { // this subject's nid // compare this nid and the passed as parameter one nidEqual = _nameIdentifier.equals(nid); } else if (nid == null) { nidEqual= true; // passed one is null also stored nid is null } // nid is done so lets see subject confirmation now SubjectConfirmation sc = subject.getSubjectConfirmation(); if (_subjectConfirmation != null ) { // this subject's SC scEqual = _subjectConfirmation.equals(sc); } else if (sc == null ) { scEqual= true; } if (!(nidEqual) || !(scEqual)) { return false; } return true; // reached here then they are equal } return false; } /** * Constructs a Subject object from a NameIdentifier object. * * @param nameIdentifier NameIdentifier object. * @exception SAMLException if it could not process the Element * properly, implying that there is an error in the sender or in * the element definition. */ public Subject(NameIdentifier nameIdentifier) throws SAMLException { if (nameIdentifier == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: null NameIdentifier " + "specified"); } throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( "nullInput")) ; } _nameIdentifier = nameIdentifier; } /** * Constructs a subject element from an existing XML block * which has already been built into a DOM. * * @param subjectElement An Element representing DOM tree for Subject object * @exception SAMLException if it could not process the Element properly, * implying that there is an error in the sender or in the * element definition. */ public Subject(org.w3c.dom.Element subjectElement) throws SAMLException { int elementCount=0; Element elt = (Element)subjectElement; String eltName = elt.getLocalName(); if (eltName == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: local name missing"); } throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString ("nullInput")) ; } if (!(eltName.equals("Subject"))) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: invalid root element"); } throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( "invalidElement")) ; } NodeList nl = subjectElement.getChildNodes(); int length = nl.getLength(); if (length == 0 ) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: No sub elements found"); } throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( "emptyElement")) ; } // TODO: sequence is not checked as yet for (int n=0; n < length; n++) { Node child = (Node)nl.item(n); if (child.getNodeType() != Node.ELEMENT_NODE) { continue; } String childName = child.getLocalName(); if (childName.equals("NameIdentifier")) { _nameIdentifier = createNameIdentifier((Element)child); elementCount++; } else if (childName.equals("SubjectConfirmation")) { _subjectConfirmation = createSubjectConfirmation((Element)child); elementCount++; } else { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: Invalid element " + "encountered."); } throw new SAMLRequesterException( SAMLUtilsCommon.bundle.getString("invalidElement")) ; } } if (elementCount > 2 ) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: more than allowed " + "elements passed"); } throw new SAMLRequesterException(SAMLUtilsCommon.bundle.getString( "moreElement")) ; } } /** * Constructs a Subject object from a SubjectConfirmation * object. * * @param subjectConfirmation SubjectConfirmation object to * be added to the object. * @exception SAMLException if subjectConfirmation is null. */ public Subject(SubjectConfirmation subjectConfirmation) throws SAMLException { if (subjectConfirmation == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: null " + "SubjectConfirmation specified"); } throw new SAMLRequesterException( SAMLUtilsCommon.bundle.getString("nullInput")) ; } _subjectConfirmation = subjectConfirmation; } /** * Sets the subject confirmation to the subject * * @param subjectConfirmation SubjectConfirmation to be set. * @return true if operation succeed. */ public boolean setSubjectConfirmation(SubjectConfirmation subjectConfirmation) { if (subjectConfirmation == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: null " + "SubjectConfirmation specified"); } return false; } _subjectConfirmation = subjectConfirmation; return true; } /** * Removes subject confirmation from the subject. * * @return true if the operation succeeds. */ public boolean removeSubjectConfirmation() { if (_nameIdentifier == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject:At least one of " + "NameIdentifier and SubjectConfirmation is mandatory"); } return false; } _subjectConfirmation = null; return true; } /** * Sets the NameIdentifier to the subject. * * @param nameIdentifier NameIdentifier to be set. * @return true if the operation succeeds. */ public boolean setNameIdentifier(NameIdentifier nameIdentifier) { if (nameIdentifier == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject: null nameIdentifier " + "specified"); } return false; } _nameIdentifier = nameIdentifier; return true; } /** * Removes NameIdentifier from the subject. * * @return true if operation succeeds. */ public boolean removeNameIdentifier() { if (_subjectConfirmation == null) { if (SAMLUtilsCommon.debug.messageEnabled()) { SAMLUtilsCommon.debug.message("Subject:At least one of " + "NameIdentifier and SubjectConfirmation is mandatory"); } return false; } _nameIdentifier = null; return true; } /** *Gets the NameIdentifier within the Subject element *@return NameIdentifier object, within this Subject. */ public NameIdentifier getNameIdentifier() { return _nameIdentifier; } /** *Gets the SubjectConfirmation within the Subject element *@return SubjectConfirmation object, within this Subject if *exists else null */ public SubjectConfirmation getSubjectConfirmation() { return _subjectConfirmation; } /** * Returns a String representation of the element. * * @return A string containing the valid XML for this element * By default name space name is prepended to the element name * example <saml:Subject> */ public java.lang.String toString() { // call toString() with includeNS true by default and declareNS false String xml = this.toString(true, false); return xml; } /** * Returns a String representation of the <Subject> * element. * * @param includeNS if true prepends all elements by their Namespace * name example <saml:Subject>. * @param declareNS if true includes the namespace within the * generated XML. * @return A string containing the valid XML for this element. */ public java.lang.String toString(boolean includeNS, boolean declareNS) { StringBuffer xml = new StringBuffer(3000); String o = SAMLUtilsCommon.makeStartElementTagXML( "Subject", includeNS, declareNS); xml.append(o).append(sc.NL); if (_nameIdentifier != null ) { xml.append(_nameIdentifier.toString(includeNS, false)); // false above as we dont want to have nested multiple // declarations of namespace } if (_subjectConfirmation != null) { xml.append(_subjectConfirmation.toString(includeNS, false)); } o = SAMLUtilsCommon.makeEndElementTagXML("Subject",includeNS); xml.append(o); return xml.toString(); } protected NameIdentifier createNameIdentifier(Element nameIdentifierElement) throws SAMLException { return new NameIdentifier(nameIdentifierElement); } protected SubjectConfirmation createSubjectConfirmation(Element subjectConfirmationElement) throws SAMLException { return new SubjectConfirmation(subjectConfirmationElement); } }