Added marker interface for assertion types.
[shibboleth/cpp-opensaml.git] / saml / saml1 / core / impl / ProtocolsImpl.cpp
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * ProtocolsImpl.cpp
19  * 
20  * Implementation classes for SAML 1.x Protocols schema
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml1/core/Assertions.h"
26 #include "saml1/core/Protocols.h"
27
28 #include <xmltooling/AbstractComplexElement.h>
29 #include <xmltooling/AbstractSimpleElement.h>
30 #include <xmltooling/impl/AnyElement.h>
31 #include <xmltooling/io/AbstractXMLObjectMarshaller.h>
32 #include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
33 #include <xmltooling/util/XMLHelper.h>
34
35 #include <ctime>
36 #include <xercesc/util/XMLUniDefs.hpp>
37
38 using namespace opensaml::saml1p;
39 using namespace opensaml::saml1;
40 using namespace xmlsignature;
41 using namespace xmltooling;
42 using namespace std;
43 using xmlconstants::XMLSIG_NS;
44 using xmlconstants::XML_ONE;
45 using samlconstants::SAML1P_NS;
46 using samlconstants::SAML1_NS;
47 using samlconstants::SAML1P_PREFIX;
48
49 #if defined (_MSC_VER)
50     #pragma warning( push )
51     #pragma warning( disable : 4250 4251 )
52 #endif
53
54 namespace opensaml {
55     namespace saml1p {
56     
57         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,AssertionArtifact);
58         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,StatusMessage);
59
60         class SAML_DLLLOCAL RespondWithImpl : public virtual RespondWith,
61             public AbstractSimpleElement,
62             public AbstractDOMCachingXMLObject,
63             public AbstractXMLObjectMarshaller,
64             public AbstractXMLObjectUnmarshaller
65         {
66             QName* m_qname;
67         public:
68             virtual ~RespondWithImpl() {
69                 delete m_qname;
70             }
71     
72             RespondWithImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
73                 : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_qname(NULL) {
74             }
75                 
76             RespondWithImpl(const RespondWithImpl& src)
77                     : AbstractXMLObject(src), AbstractSimpleElement(src), AbstractDOMCachingXMLObject(src), m_qname(NULL) {
78                 setQName(src.getQName());
79             }
80             
81             QName* getQName() const {
82                 return m_qname;
83             }
84             
85             void setQName(const QName* qname) {
86                 m_qname=prepareForAssignment(m_qname,qname);
87                 if (m_qname) {
88                     auto_ptr_XMLCh temp(m_qname->toString().c_str());
89                     setTextContent(temp.get());
90                 }
91                 else
92                     setTextContent(NULL);
93             }
94             
95             IMPL_XMLOBJECT_CLONE(RespondWith);
96         };
97
98         class SAML_DLLLOCAL SubjectQueryImpl : public virtual SubjectQuery,
99             public AbstractComplexElement,
100             public AbstractDOMCachingXMLObject,
101             public AbstractXMLObjectMarshaller,
102             public AbstractXMLObjectUnmarshaller
103         {
104             void init() {
105                 m_Subject=NULL;
106                 m_children.push_back(NULL);
107                 m_pos_Subject=m_children.begin();
108             }
109         protected:
110             SubjectQueryImpl() {
111                 init();
112             }
113         public:
114             virtual ~SubjectQueryImpl() {}
115     
116             SubjectQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
117                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
118                 init();
119             }
120                 
121             SubjectQueryImpl(const SubjectQueryImpl& src)
122                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
123                 init();
124                 if (src.getSubject())
125                     setSubject(src.getSubject()->cloneSubject());
126             }
127             
128             IMPL_TYPED_CHILD(Subject);
129     
130         protected:
131             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
132                 PROC_TYPED_CHILD(Subject,SAML1_NS,true);
133                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
134             }
135         };
136
137         class SAML_DLLLOCAL AuthenticationQueryImpl : public virtual AuthenticationQuery, public SubjectQueryImpl
138         {
139             void init() {
140                 m_AuthenticationMethod=NULL;
141             }
142         public:
143             virtual ~AuthenticationQueryImpl() {
144                 XMLString::release(&m_AuthenticationMethod);
145             }
146     
147             AuthenticationQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
148                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
149                 init();
150             }
151                 
152             AuthenticationQueryImpl(const AuthenticationQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
153                 init();
154                 setAuthenticationMethod(src.getAuthenticationMethod());
155             }
156             
157             IMPL_XMLOBJECT_CLONE(AuthenticationQuery);
158             SubjectQuery* cloneSubjectQuery() const {
159                 return cloneAuthenticationQuery();
160             }
161             Query* cloneQuery() const {
162                 return cloneAuthenticationQuery();
163             }
164             IMPL_STRING_ATTRIB(AuthenticationMethod);
165     
166         protected:
167             void marshallAttributes(DOMElement* domElement) const {
168                 MARSHALL_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
169                 SubjectQueryImpl::marshallAttributes(domElement);
170             }
171     
172             void processAttribute(const DOMAttr* attribute) {
173                 PROC_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
174                 SubjectQueryImpl::processAttribute(attribute);
175             }
176         };
177
178         class SAML_DLLLOCAL AttributeQueryImpl : public virtual AttributeQuery, public SubjectQueryImpl
179         {
180             void init() {
181                 m_Resource=NULL;
182             }
183         public:
184             virtual ~AttributeQueryImpl() {
185                 XMLString::release(&m_Resource);
186             }
187     
188             AttributeQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
189                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
190                 init();
191             }
192                 
193             AttributeQueryImpl(const AttributeQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
194                 init();
195                 setResource(src.getResource());
196                 VectorOf(AttributeDesignator) v=getAttributeDesignators();
197                 for (vector<AttributeDesignator*>::const_iterator i=src.m_AttributeDesignators.begin(); i!=src.m_AttributeDesignators.end(); i++) {
198                     if (*i) {
199                         v.push_back((*i)->cloneAttributeDesignator());
200                     }
201                 }
202             }
203             
204             IMPL_XMLOBJECT_CLONE(AttributeQuery);
205             SubjectQuery* cloneSubjectQuery() const {
206                 return cloneAttributeQuery();
207             }
208             Query* cloneQuery() const {
209                 return cloneAttributeQuery();
210             }
211             IMPL_STRING_ATTRIB(Resource);
212             IMPL_TYPED_CHILDREN(AttributeDesignator,m_children.end());
213     
214         protected:
215             void marshallAttributes(DOMElement* domElement) const {
216                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
217                 SubjectQueryImpl::marshallAttributes(domElement);
218             }
219     
220             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
221                 PROC_TYPED_CHILDREN(AttributeDesignator,SAML1_NS,true);
222                 SubjectQueryImpl::processChildElement(childXMLObject,root);
223             }
224     
225             void processAttribute(const DOMAttr* attribute) {
226                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
227                 SubjectQueryImpl::processAttribute(attribute);
228             }
229         };
230
231         class SAML_DLLLOCAL AuthorizationDecisionQueryImpl : public virtual AuthorizationDecisionQuery, public SubjectQueryImpl
232         {
233             void init() {
234                 m_Resource=NULL;
235                 m_Evidence=NULL;
236                 m_children.push_back(NULL);
237                 m_pos_Evidence=m_pos_Subject;
238                 ++m_pos_Evidence;
239             }
240         public:
241             virtual ~AuthorizationDecisionQueryImpl() {
242                 XMLString::release(&m_Resource);
243             }
244     
245             AuthorizationDecisionQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
246                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
247                 init();
248             }
249                 
250             AuthorizationDecisionQueryImpl(const AuthorizationDecisionQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
251                 init();
252                 setResource(src.getResource());
253                 if (src.getEvidence())
254                     setEvidence(src.getEvidence()->cloneEvidence());
255                 VectorOf(Action) v=getActions();
256                 for (vector<Action*>::const_iterator i=src.m_Actions.begin(); i!=src.m_Actions.end(); i++) {
257                     if (*i) {
258                         v.push_back((*i)->cloneAction());
259                     }
260                 }
261             }
262             
263             IMPL_XMLOBJECT_CLONE(AuthorizationDecisionQuery);
264             SubjectQuery* cloneSubjectQuery() const {
265                 return cloneAuthorizationDecisionQuery();
266             }
267             Query* cloneQuery() const {
268                 return cloneAuthorizationDecisionQuery();
269             }
270             IMPL_STRING_ATTRIB(Resource);
271             IMPL_TYPED_CHILD(Evidence);
272             IMPL_TYPED_CHILDREN(Action, m_pos_Evidence);
273     
274         protected:
275             void marshallAttributes(DOMElement* domElement) const {
276                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
277                 SubjectQueryImpl::marshallAttributes(domElement);
278             }
279     
280             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
281                 PROC_TYPED_CHILD(Evidence,SAML1_NS,false);
282                 PROC_TYPED_CHILDREN(Action,SAML1_NS,false);
283                 SubjectQueryImpl::processChildElement(childXMLObject,root);
284             }
285     
286             void processAttribute(const DOMAttr* attribute) {
287                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
288                 SubjectQueryImpl::processAttribute(attribute);
289             }
290         };
291
292         class SAML_DLLLOCAL RequestAbstractTypeImpl : public virtual RequestAbstractType,
293             public AbstractComplexElement,
294             public AbstractDOMCachingXMLObject,
295             public AbstractXMLObjectMarshaller,
296             public AbstractXMLObjectUnmarshaller
297         {
298             void init() {
299                 m_MinorVersion=NULL;
300                 m_RequestID=NULL;
301                 m_IssueInstant=NULL;
302                 m_children.push_back(NULL);
303                 m_Signature=NULL;
304                 m_pos_Signature=m_children.begin();
305             }
306         protected:
307             RequestAbstractTypeImpl() {
308                 init();
309             }
310         public:
311             virtual ~RequestAbstractTypeImpl() {
312                 XMLString::release(&m_MinorVersion);
313                 XMLString::release(&m_RequestID);
314                 delete m_IssueInstant;
315             }
316     
317             RequestAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
318                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
319                 init();
320             }
321                 
322             RequestAbstractTypeImpl(const RequestAbstractTypeImpl& src)
323                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
324                 init();
325                 setMinorVersion(src.m_MinorVersion);
326                 setRequestID(src.getRequestID());
327                 setIssueInstant(src.getIssueInstant());
328                 if (src.getSignature())
329                     setSignature(src.getSignature()->cloneSignature());
330                 VectorOf(RespondWith) v=getRespondWiths();
331                 for (vector<RespondWith*>::const_iterator i=src.m_RespondWiths.begin(); i!=src.m_RespondWiths.end(); i++) {
332                     if (*i) {
333                         v.push_back((*i)->cloneRespondWith());
334                     }
335                 }
336             }
337             
338             //IMPL_TYPED_CHILD(Signature);
339             // Need customized setter.
340         protected:
341             Signature* m_Signature;
342             list<XMLObject*>::iterator m_pos_Signature;
343         public:
344             Signature* getSignature() const {
345                 return m_Signature;
346             }
347             
348             void setSignature(Signature* sig) {
349                 prepareForAssignment(m_Signature,sig);
350                 *m_pos_Signature=m_Signature=sig;
351                 // Sync content reference back up.
352                 if (m_Signature)
353                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
354             }
355
356             IMPL_INTEGER_ATTRIB(MinorVersion);
357             IMPL_STRING_ATTRIB(RequestID);    // have to special-case getXMLID
358             const XMLCh* getXMLID() const {
359                 pair<bool,int> v = getMinorVersion();
360                 return (!v.first || v.second > 0) ? m_RequestID : NULL;
361             }
362             const XMLCh* getID() const {
363                 return getRequestID();
364             }
365             IMPL_DATETIME_ATTRIB(IssueInstant,0);
366             IMPL_TYPED_CHILDREN(RespondWith,m_pos_Signature);
367     
368         protected:
369             void marshallAttributes(DOMElement* domElement) const {
370                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
371                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
372                 if (!m_MinorVersion)
373                     const_cast<RequestAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
374                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
375                 if (!m_RequestID)
376                     const_cast<RequestAbstractTypeImpl*>(this)->m_RequestID=SAMLConfig::getConfig().generateIdentifier();
377                 MARSHALL_ID_ATTRIB(RequestID,REQUESTID,NULL);
378                 if (!m_IssueInstant) {
379                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
380                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
381                 }
382                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
383             }
384
385             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
386                 PROC_TYPED_CHILDREN(RespondWith,SAML1P_NS,false);
387                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
388                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
389             }
390
391             void processAttribute(const DOMAttr* attribute) {
392                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
393                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
394                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
395                         throw UnmarshallingException("Request has invalid major version.");
396                 }
397                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
398                 PROC_ID_ATTRIB(RequestID,REQUESTID,NULL);
399                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
400             }
401         };
402
403         class SAML_DLLLOCAL RequestImpl : public virtual Request, public RequestAbstractTypeImpl
404         {
405             void init() {
406                 m_children.push_back(NULL);
407                 m_Query=NULL;
408                 m_pos_Query=m_pos_Signature;
409                 ++m_pos_Query;
410             }
411         public:
412             virtual ~RequestImpl() {}
413     
414             RequestImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
415                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
416                 init();
417             }
418                 
419             RequestImpl(const RequestImpl& src) : AbstractXMLObject(src), RequestAbstractTypeImpl(src) {
420                 init();
421                 if (src.getQuery())
422                     setQuery(src.getQuery()->cloneQuery());
423                 VectorOf(AssertionIDReference) v=getAssertionIDReferences();
424                 for (vector<AssertionIDReference*>::const_iterator i=src.m_AssertionIDReferences.begin(); i!=src.m_AssertionIDReferences.end(); i++) {
425                     if (*i) {
426                         v.push_back((*i)->cloneAssertionIDReference());
427                     }
428                 }
429                 VectorOf(AssertionArtifact) v2=getAssertionArtifacts();
430                 for (vector<AssertionArtifact*>::const_iterator i=src.m_AssertionArtifacts.begin(); i!=src.m_AssertionArtifacts.end(); i++) {
431                     if (*i) {
432                         v2.push_back((*i)->cloneAssertionArtifact());
433                     }
434                 }
435             }
436             
437             IMPL_XMLOBJECT_CLONE(Request);
438             RequestAbstractType* cloneRequestAbstractType() const {
439                 return cloneRequest();
440             }
441             IMPL_TYPED_CHILD(Query);
442             
443             SubjectQuery* getSubjectQuery() const {
444                 return dynamic_cast<SubjectQuery*>(getQuery());
445             }
446             AuthenticationQuery* getAuthenticationQuery() const {
447                 return dynamic_cast<AuthenticationQuery*>(getQuery());
448             }
449             AttributeQuery* getAttributeQuery() const {
450                 return dynamic_cast<AttributeQuery*>(getQuery());
451             }
452             AuthorizationDecisionQuery* getAuthorizationDecisionQuery() const {
453                 return dynamic_cast<AuthorizationDecisionQuery*>(getQuery());
454             }
455
456             void setSubjectQuery(SubjectQuery* q) {
457                 setQuery(q);
458             }
459             void setAuthenticationQuery(AuthenticationQuery* q) {
460                 setQuery(q);
461             }
462             void setAttributeQuery(AttributeQuery* q) {
463                 setQuery(q);
464             }
465             void setAuthorizationDecisionQuery(AuthorizationDecisionQuery* q) {
466                 setQuery(q);
467             }
468             
469             IMPL_TYPED_CHILDREN(AssertionIDReference, m_children.end());
470             IMPL_TYPED_CHILDREN(AssertionArtifact, m_children.end());
471     
472         protected:
473             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
474                 PROC_TYPED_CHILD(Query,SAML1P_NS,true);
475                 PROC_TYPED_CHILDREN(AssertionIDReference,SAML1_NS,false);
476                 PROC_TYPED_CHILDREN(AssertionArtifact,SAML1P_NS,false);
477                 RequestAbstractTypeImpl::processChildElement(childXMLObject,root);
478             }
479         };
480
481         class SAML_DLLLOCAL StatusCodeImpl : public virtual StatusCode,
482             public AbstractComplexElement,
483             public AbstractDOMCachingXMLObject,
484             public AbstractXMLObjectMarshaller,
485             public AbstractXMLObjectUnmarshaller
486         {
487             void init() {
488                 m_Value=NULL;
489                 m_children.push_back(NULL);
490                 m_StatusCode=NULL;
491                 m_pos_StatusCode=m_children.begin();
492             }
493         public:
494             virtual ~StatusCodeImpl() {
495                 delete m_Value;
496             }
497     
498             StatusCodeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
499                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
500                 init();
501             }
502                 
503             StatusCodeImpl(const StatusCodeImpl& src)
504                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
505                 init();
506                 setValue(src.getValue());
507                 if (src.getStatusCode())
508                     setStatusCode(src.getStatusCode()->cloneStatusCode());
509             }
510             
511             IMPL_XMLOBJECT_CLONE(StatusCode);
512             IMPL_XMLOBJECT_ATTRIB(Value,QName);
513             IMPL_TYPED_CHILD(StatusCode);
514     
515         protected:
516             void marshallAttributes(DOMElement* domElement) const {
517                 MARSHALL_QNAME_ATTRIB(Value,VALUE,NULL);
518             }
519
520             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
521                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,true);
522                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
523             }
524
525             void processAttribute(const DOMAttr* attribute) {
526                 PROC_QNAME_ATTRIB(Value,VALUE,NULL);
527             }
528         };
529
530         class SAML_DLLLOCAL StatusDetailImpl : public virtual StatusDetail,
531             public AbstractComplexElement,
532             public AbstractDOMCachingXMLObject,
533             public AbstractXMLObjectMarshaller,
534             public AbstractXMLObjectUnmarshaller
535         {
536         public:
537             virtual ~StatusDetailImpl() {}
538     
539             StatusDetailImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
540                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
541             }
542                 
543             StatusDetailImpl(const StatusDetailImpl& src)
544                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
545                 VectorOf(XMLObject) v=getUnknownXMLObjects();
546                 for (vector<XMLObject*>::const_iterator i=src.m_UnknownXMLObjects.begin(); i!=src.m_UnknownXMLObjects.end(); ++i)
547                     v.push_back((*i)->clone());
548             }
549             
550             IMPL_XMLOBJECT_CLONE(StatusDetail);
551             IMPL_XMLOBJECT_CHILDREN(UnknownXMLObject,m_children.end());
552     
553         protected:
554             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
555                 getUnknownXMLObjects().push_back(childXMLObject);
556             }
557         };
558
559         class SAML_DLLLOCAL StatusImpl : public virtual Status,
560             public AbstractComplexElement,
561             public AbstractDOMCachingXMLObject,
562             public AbstractXMLObjectMarshaller,
563             public AbstractXMLObjectUnmarshaller
564         {
565             void init() {
566                 m_children.push_back(NULL);
567                 m_children.push_back(NULL);
568                 m_children.push_back(NULL);
569                 m_StatusCode=NULL;
570                 m_pos_StatusCode=m_children.begin();
571                 m_StatusMessage=NULL;
572                 m_pos_StatusMessage=m_pos_StatusCode;
573                 ++m_pos_StatusMessage;
574                 m_StatusDetail=NULL;
575                 m_pos_StatusDetail=m_pos_StatusMessage;
576                 ++m_pos_StatusDetail;
577             }
578         public:
579             virtual ~StatusImpl() {}
580     
581             StatusImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
582                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
583                 init();
584             }
585                 
586             StatusImpl(const StatusImpl& src)
587                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
588                 init();
589                 if (src.getStatusCode())
590                     setStatusCode(src.getStatusCode()->cloneStatusCode());
591                 if (src.getStatusMessage())
592                     setStatusMessage(src.getStatusMessage()->cloneStatusMessage());
593                 if (src.getStatusDetail())
594                     setStatusDetail(src.getStatusDetail()->cloneStatusDetail());
595             }
596             
597             IMPL_XMLOBJECT_CLONE(Status);
598             IMPL_TYPED_CHILD(StatusCode);
599             IMPL_TYPED_CHILD(StatusMessage);
600             IMPL_TYPED_CHILD(StatusDetail);
601     
602         protected:
603             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
604                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,false);
605                 PROC_TYPED_CHILD(StatusMessage,SAML1P_NS,false);
606                 PROC_TYPED_CHILD(StatusDetail,SAML1P_NS,false);
607                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
608             }
609         };
610
611         class SAML_DLLLOCAL ResponseAbstractTypeImpl : public virtual ResponseAbstractType,
612             public AbstractComplexElement,
613             public AbstractDOMCachingXMLObject,
614             public AbstractXMLObjectMarshaller,
615             public AbstractXMLObjectUnmarshaller
616         {
617             void init() {
618                 m_MinorVersion=NULL;
619                 m_ResponseID=NULL;
620                 m_InResponseTo=NULL;
621                 m_IssueInstant=NULL;
622                 m_Recipient=NULL;
623                 m_children.push_back(NULL);
624                 m_Signature=NULL;
625                 m_pos_Signature=m_children.begin();
626             }
627         protected:
628             ResponseAbstractTypeImpl() {
629                 init();
630             }
631         public:
632             virtual ~ResponseAbstractTypeImpl() {
633                 XMLString::release(&m_MinorVersion);
634                 XMLString::release(&m_ResponseID);
635                 XMLString::release(&m_InResponseTo);
636                 XMLString::release(&m_Recipient);
637                 delete m_IssueInstant;
638             }
639     
640             ResponseAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
641                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
642                 init();
643             }
644                 
645             ResponseAbstractTypeImpl(const ResponseAbstractTypeImpl& src)
646                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
647                 init();
648                 setMinorVersion(src.m_MinorVersion);
649                 setResponseID(src.getResponseID());
650                 setInResponseTo(src.getInResponseTo());
651                 setIssueInstant(src.getIssueInstant());
652                 setRecipient(src.getRecipient());
653                 if (src.getSignature())
654                     setSignature(src.getSignature()->cloneSignature());
655             }
656
657             //IMPL_TYPED_CHILD(Signature);
658             // Need customized setter.
659         protected:
660             Signature* m_Signature;
661             list<XMLObject*>::iterator m_pos_Signature;
662         public:
663             Signature* getSignature() const {
664                 return m_Signature;
665             }
666             
667             void setSignature(Signature* sig) {
668                 prepareForAssignment(m_Signature,sig);
669                 *m_pos_Signature=m_Signature=sig;
670                 // Sync content reference back up.
671                 if (m_Signature)
672                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
673             }
674
675             IMPL_INTEGER_ATTRIB(MinorVersion);
676             IMPL_STRING_ATTRIB(ResponseID);    // have to special-case getXMLID
677             const XMLCh* getXMLID() const {
678                 pair<bool,int> v = getMinorVersion();
679                 return (!v.first || v.second > 0) ? m_ResponseID : NULL;
680             }
681             const XMLCh* getID() const {
682                 return getResponseID();
683             }
684             IMPL_STRING_ATTRIB(InResponseTo);
685             IMPL_DATETIME_ATTRIB(IssueInstant,0);
686             IMPL_STRING_ATTRIB(Recipient);
687     
688         protected:
689             void marshallAttributes(DOMElement* domElement) const {
690                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
691                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
692                 if (!m_MinorVersion)
693                     const_cast<ResponseAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
694                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
695                 if (!m_ResponseID)
696                     const_cast<ResponseAbstractTypeImpl*>(this)->m_ResponseID=SAMLConfig::getConfig().generateIdentifier();
697                 MARSHALL_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
698                 MARSHALL_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
699                 if (!m_IssueInstant) {
700                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
701                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
702                 }
703                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
704                 MARSHALL_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
705             }
706
707             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
708                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
709                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
710             }
711
712             void processAttribute(const DOMAttr* attribute) {
713                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
714                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
715                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
716                         throw UnmarshallingException("Response has invalid major version.");
717                 }
718                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
719                 PROC_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
720                 PROC_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
721                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
722                 PROC_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
723             }
724         };
725
726         class SAML_DLLLOCAL ResponseImpl : public virtual Response, public ResponseAbstractTypeImpl
727         {
728             void init() {
729                 m_children.push_back(NULL);
730                 m_Status=NULL;
731                 m_pos_Status=m_pos_Signature;
732                 ++m_pos_Status;
733             }
734         public:
735             virtual ~ResponseImpl() {}
736     
737             ResponseImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
738                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
739                 init();
740             }
741                 
742             ResponseImpl(const ResponseImpl& src) : AbstractXMLObject(src), ResponseAbstractTypeImpl(src) {
743                 init();
744                 if (src.getStatus())
745                     setStatus(src.getStatus()->cloneStatus());
746                 VectorOf(saml1::Assertion) v=getAssertions();
747                 for (vector<saml1::Assertion*>::const_iterator i=src.m_Assertions.begin(); i!=src.m_Assertions.end(); i++) {
748                     if (*i) {
749                         v.push_back((*i)->cloneAssertion());
750                     }
751                 }
752             }
753             
754             IMPL_XMLOBJECT_CLONE(Response);
755             ResponseAbstractType* cloneResponseAbstractType() const {
756                 return cloneResponse();
757             }
758             IMPL_TYPED_CHILD(Status);
759             IMPL_TYPED_FOREIGN_CHILDREN(Assertion,saml1,m_children.end());
760     
761         protected:
762             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
763                 PROC_TYPED_CHILD(Status,SAML1P_NS,false);
764                 PROC_TYPED_FOREIGN_CHILDREN(Assertion,saml1,SAML1_NS,true);
765                 ResponseAbstractTypeImpl::processChildElement(childXMLObject,root);
766             }
767         };
768
769     };
770 };
771
772 #if defined (_MSC_VER)
773     #pragma warning( pop )
774 #endif
775
776 // Builder Implementations
777
778 IMPL_XMLOBJECTBUILDER(AssertionArtifact);
779 IMPL_XMLOBJECTBUILDER(AttributeQuery);
780 IMPL_XMLOBJECTBUILDER(AuthenticationQuery);
781 IMPL_XMLOBJECTBUILDER(AuthorizationDecisionQuery);
782 IMPL_XMLOBJECTBUILDER(Request);
783 IMPL_XMLOBJECTBUILDER(RespondWith);
784 IMPL_XMLOBJECTBUILDER(Response);
785 IMPL_XMLOBJECTBUILDER(Status);
786 IMPL_XMLOBJECTBUILDER(StatusCode);
787 IMPL_XMLOBJECTBUILDER(StatusDetail);
788 IMPL_XMLOBJECTBUILDER(StatusMessage);
789
790 // Unicode literals
791 const XMLCh RequestAbstractType::LOCAL_NAME[] =             {chNull};
792 const XMLCh RequestAbstractType::TYPE_NAME[] =              UNICODE_LITERAL_19(R,e,q,u,e,s,t,A,b,s,t,r,a,c,t,T,y,p,e);
793 const XMLCh RequestAbstractType::MINORVERSION_ATTRIB_NAME[] =   UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
794 const XMLCh RequestAbstractType::REQUESTID_ATTRIB_NAME[] =      UNICODE_LITERAL_9(R,e,q,u,e,s,t,I,D);
795 const XMLCh RequestAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =   UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
796 const XMLCh ResponseAbstractType::LOCAL_NAME[] =            {chNull};
797 const XMLCh ResponseAbstractType::TYPE_NAME[] =             UNICODE_LITERAL_20(R,e,s,p,o,n,s,e,A,b,s,t,r,a,c,t,T,y,p,e);
798 const XMLCh ResponseAbstractType::MINORVERSION_ATTRIB_NAME[] =  UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
799 const XMLCh ResponseAbstractType::RESPONSEID_ATTRIB_NAME[] =    UNICODE_LITERAL_10(R,e,s,p,o,n,s,e,I,D);
800 const XMLCh ResponseAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
801 const XMLCh ResponseAbstractType::INRESPONSETO_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,n,R,e,s,p,o,n,s,e,T,o);
802 const XMLCh ResponseAbstractType::RECIPIENT_ATTRIB_NAME[] =     UNICODE_LITERAL_9(R,e,c,i,p,i,e,n,t);
803 const XMLCh AssertionArtifact::LOCAL_NAME[] =               UNICODE_LITERAL_17(A,s,s,e,r,t,i,o,n,A,r,t,i,f,a,c,t);
804 const XMLCh AttributeQuery::LOCAL_NAME[] =                  UNICODE_LITERAL_14(A,t,t,r,i,b,u,t,e,Q,u,e,r,y);
805 const XMLCh AttributeQuery::TYPE_NAME[] =                   UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,Q,u,e,r,y,T,y,p,e);
806 const XMLCh AttributeQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
807 const XMLCh AuthenticationQuery::LOCAL_NAME[] =             UNICODE_LITERAL_19(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y);
808 const XMLCh AuthenticationQuery::TYPE_NAME[] =              UNICODE_LITERAL_23(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y,T,y,p,e);
809 const XMLCh AuthenticationQuery::AUTHENTICATIONMETHOD_ATTRIB_NAME[] =   UNICODE_LITERAL_20(A,u,t,h,e,n,t,i,c,a,t,i,o,n,M,e,t,h,o,d);
810 const XMLCh AuthorizationDecisionQuery::LOCAL_NAME[] =      UNICODE_LITERAL_26(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y);
811 const XMLCh AuthorizationDecisionQuery::TYPE_NAME[] =       UNICODE_LITERAL_30(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y,T,y,p,e);
812 const XMLCh AuthorizationDecisionQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
813 const XMLCh Query::LOCAL_NAME[] =                           UNICODE_LITERAL_5(Q,u,e,r,y);
814 const XMLCh Request::LOCAL_NAME[] =                         UNICODE_LITERAL_7(R,e,q,u,e,s,t);
815 const XMLCh Request::TYPE_NAME[] =                          UNICODE_LITERAL_11(R,e,q,u,e,s,t,T,y,p,e);
816 const XMLCh RespondWith::LOCAL_NAME[] =                     UNICODE_LITERAL_11(R,e,s,p,o,n,d,W,i,t,h);
817 const XMLCh Response::LOCAL_NAME[] =                        UNICODE_LITERAL_8(R,e,s,p,o,n,s,e);
818 const XMLCh Response::TYPE_NAME[] =                         UNICODE_LITERAL_12(R,e,s,p,o,n,s,e,T,y,p,e);
819 const XMLCh Status::LOCAL_NAME[] =                          UNICODE_LITERAL_6(S,t,a,t,u,s);
820 const XMLCh Status::TYPE_NAME[] =                           UNICODE_LITERAL_10(S,t,a,t,u,s,T,y,p,e);
821 const XMLCh StatusCode::LOCAL_NAME[] =                      UNICODE_LITERAL_10(S,t,a,t,u,s,C,o,d,e);
822 const XMLCh StatusCode::TYPE_NAME[] =                       UNICODE_LITERAL_14(S,t,a,t,u,s,C,o,d,e,T,y,p,e);
823 const XMLCh StatusCode::VALUE_ATTRIB_NAME[] =               UNICODE_LITERAL_5(V,a,l,u,e);
824 const XMLCh StatusDetail::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,t,a,t,u,s,D,e,t,a,i,l);
825 const XMLCh StatusDetail::TYPE_NAME[] =                     UNICODE_LITERAL_16(S,t,a,t,u,s,D,e,t,a,i,l,T,y,p,e);
826 const XMLCh StatusMessage::LOCAL_NAME[] =                   UNICODE_LITERAL_13(S,t,a,t,u,s,M,e,s,s,a,g,e);
827 const XMLCh SubjectQuery::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,u,b,j,e,c,t,Q,u,e,r,y);
828
829 #define XCH(ch) chLatin_##ch
830 #define XNUM(d) chDigit_##d
831
832 const XMLCh _SUCCESS[] =                                    UNICODE_LITERAL_7(S,u,c,c,e,s,s);
833 const XMLCh _REQUESTER[] =                                  UNICODE_LITERAL_9(R,e,q,u,e,s,t,e,r);
834 const XMLCh _RESPONDER[] =                                  UNICODE_LITERAL_9(R,e,s,p,o,n,d,e,r);
835 const XMLCh _VERSIONMISMATCH[] =                            UNICODE_LITERAL_15(V,e,r,s,i,o,n,M,i,s,m,a,t,c,h);
836  
837 QName StatusCode::SUCCESS(SAML1P_NS,_SUCCESS,SAML1P_PREFIX);
838 QName StatusCode::REQUESTER(SAML1P_NS,_REQUESTER,SAML1P_PREFIX);
839 QName StatusCode::RESPONDER(SAML1P_NS,_RESPONDER,SAML1P_PREFIX);
840 QName StatusCode::VERSIONMISMATCH(SAML1P_NS,_VERSIONMISMATCH,SAML1P_PREFIX);