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