The OpenSAML V2 software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only.
OSTwoUsrManJavaAnyTypes
Dealing with any
Types
A couple of elements within the SAML schema are defined with a special, wildcard, type known as an anyType
. These elements can take any valid XML as content which translates to the SAMLObjects representing those element allowing any XMLObject as a child. Specifically these are, in SAML 1.X: Advice
, SubjectConfirmationData
, AttributeValue
, and StatusDetail
and in SAML 2.0: SubjectConfirmationData
, Advice
, AuthnContextDecl
, AttributeValue
, Extensions
, StatusDetail
, StatusResponse
, and all the metadata endpoint elements.
Adding Content to any
Types
Every SAMLObject representing an XML element of type anyType
extends org.opensaml.xml.ElementExtensibleXMLObject
which defines the method getUnknownXMLObjects()
. XMLObjects representing the content to be added to the SAMLObject should be added to the list returned by this method. These child objects will then be marshalled as any other children object.
Building XMLObjects for use as content works a bit differently than the normal method for building objects, because some child elements are expected to have a specific name (e.g. AttributeValue) but can still contain any valid XML. To build the XMLObject in this case get the builder for the XMLObject as you normally would, but instead of invoking buildObject()
you need to use either buildObject(String, String, String)
or builidObject(QName)
to override the default element name. It's also good practice to explicitly state the schema type of this object as it makes it easier for the receiver of the message to parse it. To do this pass in a QName
that represents the schema type in as an additional, final, argument to the methods just discussed. All the objects in the OpenSAML library, on their interface, define a static QName
called TYPE_NAME that can be used as this argument.
Reading Content of any
Types
The method getUnknownXMLObjects()
provides access to the unknown content of SAMLObjects defined with the any
type. Reading information from this list can be problematic if you're not exactly sure what is in the returned list. If, during the unmarshalling process, the library encountered an element whose xsi:type or element name was not recognized (i.e. was not explicitly listed in the OpenSAML configuration files) the library will unmarshall the element into the org.opensaml.xml.ElementProxy
XMLObject. No information is lost, but if you were expecting to cast the object to a specific SAMLObject interface you'll receive a class cast exception when you try. If the library understands the element or element type, though, it is safe to cast it to the respecting interface.
AttributeValues
Probably the most commonly encountered example of this is the AttributeValue
element. There is an AttributeValue interface but nothing implements it, which means you can't cast classes to it. It exists simply to hold name constants which may be used when building other XMLObjects via the XMLObjectBuilder#buildObject(String, String, String)
or XMLObjectBuilder#buildObject(QName)
methods.
Here's an example of an AttributeValue
that carries string content. The AttributeValue
element will express an xsi:type
of xs:string
.
// Normally built Attribute object Attribute attribute; XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); stringValue.setValue("myStringValue"); attribute.getAttributeValues().add(stringValue);
Here's an example of an AttributeValue
that carries element content. An XSAny
object is used to represent the AttributeValue
, in order to allow the addition of element children. The Role
child element in the example is also represented by an XSAny
. Another and more correct approach would be to implement XML object provider support for the Role
element.
XMLObjectBuilderFactory bf = Configuration.getBuilderFactory(); XMLObjectBuilder<XSAny> xsAnyBuilder = bf.getBuilder(XSAny.TYPE_NAME); XSAny role = xsAnyBuilder.buildObject("http://www.hhs.gov/healthit/nhin", "Role", "nhin"); role.getUnknownAttributes().put(new QName("code"), "112247003"); role.getUnknownAttributes().put(new QName("codeSystem"), "2.16.840.1.113883.6.96"); role.getUnknownAttributes().put(new QName("codeSystemName"), "SNOMED CT"); role.getUnknownAttributes().put(new QName("displayName"), "Medical doctor"); XSAny roleAttributeValue = xsAnyBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME); roleAttributeValue.getUnknownXMLObjects().add(role); Attribute attribute = (Attribute) bf.getBuilder(Attribute.DEFAULT_ELEMENT_NAME).buildObject(Attribute.DEFAULT_ELEMENT_NAME); attribute.setName("UserRole"); attribute.setNameFormat("http://www.hhs.gov/healthit/nhin"); attribute.getAttributeValues().add(roleAttributeValue);
When marshalled and serialized, this produces the following XML:
<saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="UserRole" NameFormat="http://www.hhs.gov/healthit/nhin"> <saml2:AttributeValue> <nhin:Role xmlns:nhin="http://www.hhs.gov/healthit/nhin" code="112247003" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Medical doctor"/> </saml2:AttributeValue> </saml2:Attribute>