Import from 1.9a8 tarball
[mozilla-extra.git] / extensions / webservices / schema / src / nsSchemaLoader.cpp
blob0005bc00b8b47ba12aff564a4662629435bdc3de
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Vidur Apparao <vidur@netscape.com> (original author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsSchemaPrivate.h"
40 #include "nsSchemaLoader.h"
41 #include "nsIWebServiceErrorHandler.h"
43 // content includes
44 #include "nsIContent.h"
45 #include "nsIDocument.h"
46 #include "nsIDOMDocument.h"
47 #include "nsIDOM3Node.h"
49 // loading includes
50 #include "nsIXMLHttpRequest.h"
51 #include "nsIDOMEvent.h"
52 #include "nsIDOMEventListener.h"
53 #include "nsIDOMEventTarget.h"
54 #include "nsNetUtil.h"
55 #include "nsIParserService.h"
57 // string includes
58 #include "nsReadableUtils.h"
60 // XPConnect includes
61 #include "nsIXPConnect.h"
62 #include "nsIScriptSecurityManager.h"
63 #include "nsIPrincipal.h"
65 // XPCOM includes
66 #include "nsIServiceManager.h"
67 #include "nsIComponentManager.h"
68 #include "nsStaticAtom.h"
70 ////////////////////////////////////////////////////////////
72 // nsSchemaAtoms implementation
74 ////////////////////////////////////////////////////////////
76 // define storage for all atoms
77 #define SCHEMA_ATOM(_name, _value) nsIAtom* nsSchemaAtoms::_name;
78 #include "nsSchemaAtomList.h"
79 #undef SCHEMA_ATOM
81 static const nsStaticAtom atomInfo[] = {
82 #define SCHEMA_ATOM(_name, _value) { _value, &nsSchemaAtoms::_name },
83 #include "nsSchemaAtomList.h"
84 #undef SCHEMA_ATOM
87 nsresult
88 nsSchemaAtoms::AddRefAtoms()
90 return NS_RegisterStaticAtoms(atomInfo, NS_ARRAY_LENGTH(atomInfo));
93 ////////////////////////////////////////////////////////////
95 // LoadListener implementation
97 ////////////////////////////////////////////////////////////
99 class LoadListener : public nsIDOMEventListener {
100 public:
101 LoadListener(nsSchemaLoader* aLoader,
102 nsISchemaLoadListener* aListener,
103 nsIXMLHttpRequest* aRequest);
104 virtual ~LoadListener();
106 NS_DECL_ISUPPORTS
107 NS_DECL_NSIDOMEVENTLISTENER
109 private:
110 nsSchemaLoader* mLoader;
111 nsCOMPtr<nsISchemaLoadListener> mListener;
112 nsCOMPtr<nsIXMLHttpRequest> mRequest;
113 nsString mURI;
116 LoadListener::LoadListener(nsSchemaLoader* aLoader,
117 nsISchemaLoadListener* aListener,
118 nsIXMLHttpRequest* aRequest)
120 mLoader = aLoader;
121 NS_ADDREF(mLoader);
122 mListener = aListener;
123 mRequest = aRequest;
126 LoadListener::~LoadListener()
128 NS_IF_RELEASE(mLoader);
131 NS_IMPL_ISUPPORTS1(LoadListener, nsIDOMEventListener)
133 /* void handleEvent (in nsIDOMEvent event); */
134 NS_IMETHODIMP
135 LoadListener::HandleEvent(nsIDOMEvent *event)
137 nsresult rv;
139 PRUint32 httpStatus;
140 mRequest->GetStatus(&httpStatus);
142 nsCOMPtr<nsISchema> schema;
144 nsAutoString eventType;
145 event->GetType(eventType);
147 PRBool succeeded = (httpStatus / 100 == 2);
149 // if we loaded fine, and not http/https, we assume success in loaded the file.
150 if (!succeeded && eventType.EqualsLiteral("load")) {
151 nsCOMPtr<nsIChannel> channel;
152 mRequest->GetChannel(getter_AddRefs(channel));
153 if (channel) {
154 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
156 // if qi to httpChannel fails, it isn't a http:// or https:// request
157 if (!httpChannel) {
158 succeeded = PR_TRUE;
163 if (succeeded && eventType.EqualsLiteral("load")) {
164 nsCOMPtr<nsIDOMDocument> document;
166 rv = mRequest->GetResponseXML(getter_AddRefs(document));
167 if (NS_SUCCEEDED(rv)) {
168 nsCOMPtr<nsIDOMElement> element;
170 if (document)
171 document->GetDocumentElement(getter_AddRefs(element));
173 //XXXTelemac TODO Use an nsIWebServiceErrorHandler instead of nsnull
174 if (element)
175 rv = mLoader->ProcessSchemaElement(element, nsnull, getter_AddRefs(schema));
176 else
177 rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
180 else {
181 rv = NS_ERROR_SCHEMA_LOADING_ERROR;
184 //XXXTelemac OnError call replace by use of nsIWebServiceErrorHandler
185 //XXXTelemac in sub-processing methods.
187 if (mListener) {
188 if (NS_SUCCEEDED(rv))
189 mListener->OnLoad(schema);
190 else
191 mListener->OnError(rv, NS_LITERAL_STRING("Failure loading"));
194 NS_IF_RELEASE(mLoader);
195 mListener = nsnull;
196 mRequest = nsnull;
198 return NS_OK;
201 ////////////////////////////////////////////////////////////
203 // nsBuiltinSchemaCollection implementation
205 ////////////////////////////////////////////////////////////
206 nsBuiltinSchemaCollection::nsBuiltinSchemaCollection()
210 nsresult
211 nsBuiltinSchemaCollection::Init()
213 return (mBuiltinTypesHash.Init() && mSOAPTypeHash.Init()) ? NS_OK
214 : NS_ERROR_FAILURE;
217 NS_IMPL_ISUPPORTS1(nsBuiltinSchemaCollection,
218 nsISchemaCollection)
220 /* nsISchema getSchema (in AString targetNamespace); */
221 NS_IMETHODIMP
222 nsBuiltinSchemaCollection::GetSchema(const nsAString & targetNamespace,
223 nsISchema **_retval)
225 NS_ENSURE_ARG_POINTER(_retval);
226 *_retval = nsnull;
227 return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
230 /* nsISchemaElement getElement (in AString name, in AString namespace); */
231 NS_IMETHODIMP
232 nsBuiltinSchemaCollection::GetElement(const nsAString & aName,
233 const nsAString & aNamespace,
234 nsISchemaElement **_retval)
236 if (aNamespace.IsEmpty()) {
237 NS_WARNING("nsSchemaLoader::GetSchema(nsAString,nsISchema): "
238 "Invalid |targetNamespace| is empty");
240 return NS_ERROR_INVALID_ARG;
243 NS_ENSURE_ARG_POINTER(_retval);
244 *_retval = nsnull;
245 return NS_ERROR_FAILURE;
248 /* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
249 NS_IMETHODIMP
250 nsBuiltinSchemaCollection::GetAttribute(const nsAString & aName,
251 const nsAString & aNamespace,
252 nsISchemaAttribute **_retval)
254 NS_ENSURE_ARG_POINTER(_retval);
255 *_retval = nsnull;
256 return NS_ERROR_FAILURE;
259 static PRBool
260 IsSchemaNamespace(const nsAString& aNamespace)
262 if (aNamespace.EqualsLiteral(NS_SCHEMA_2001_NAMESPACE) ||
263 aNamespace.EqualsLiteral(NS_SCHEMA_1999_NAMESPACE)) {
264 return PR_TRUE;
266 else {
267 return PR_FALSE;
271 static PRBool
272 IsSOAPNamespace(const nsAString& aNamespace)
274 if (aNamespace.EqualsLiteral(NS_SOAP_1_1_ENCODING_NAMESPACE) ||
275 aNamespace.EqualsLiteral(NS_SOAP_1_2_ENCODING_NAMESPACE)) {
276 return PR_TRUE;
278 else {
279 return PR_FALSE;
283 /* nsISchemaType getType (in AString name, in AString namespace); */
284 NS_IMETHODIMP
285 nsBuiltinSchemaCollection::GetType(const nsAString & aName,
286 const nsAString & aNamespace,
287 nsISchemaType **_retval)
289 if (IsSchemaNamespace(aNamespace)) {
290 return GetBuiltinType(aName, aNamespace, _retval);
293 if (IsSOAPNamespace(aNamespace)) {
294 return GetSOAPType(aName, aNamespace, _retval);
297 return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
300 nsresult
301 nsBuiltinSchemaCollection::GetBuiltinType(const nsAString& aName,
302 const nsAString& aNamespace,
303 nsISchemaType** aType)
305 if (!mBuiltinTypesHash.Get(aName, aType)) {
306 nsCOMPtr<nsIAtom> typeName = do_GetAtom(aName);
307 PRUint16 typeVal;
308 if (typeName == nsSchemaAtoms::sAnyType_atom) {
309 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYTYPE;
311 else if (typeName == nsSchemaAtoms::sString_atom) {
312 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
314 else if (typeName == nsSchemaAtoms::sNormalizedString_atom) {
315 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NORMALIZED_STRING;
317 else if (typeName == nsSchemaAtoms::sToken_atom) {
318 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TOKEN;
320 else if (typeName == nsSchemaAtoms::sByte_atom) {
321 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BYTE;
323 else if (typeName == nsSchemaAtoms::sUnsignedByte_atom) {
324 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDBYTE;
326 else if (typeName == nsSchemaAtoms::sBase64Binary_atom) {
327 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BASE64BINARY;
329 else if (typeName == nsSchemaAtoms::sHexBinary_atom) {
330 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_HEXBINARY;
332 else if (typeName == nsSchemaAtoms::sInteger_atom) {
333 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INTEGER;
335 else if (typeName == nsSchemaAtoms::sPositiveInteger_atom) {
336 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER;
338 else if (typeName == nsSchemaAtoms::sNegativeInteger_atom) {
339 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NEGATIVEINTEGER;
341 else if (typeName == nsSchemaAtoms::sNonnegativeInteger_atom) {
342 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONNEGATIVEINTEGER;
344 else if (typeName == nsSchemaAtoms::sNonpositiveInteger_atom) {
345 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NONPOSITIVEINTEGER;
347 else if (typeName == nsSchemaAtoms::sInt_atom) {
348 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_INT;
350 else if (typeName == nsSchemaAtoms::sUnsignedInt_atom) {
351 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDINT;
353 else if (typeName == nsSchemaAtoms::sLong_atom) {
354 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LONG;
356 else if (typeName == nsSchemaAtoms::sUnsignedLong_atom) {
357 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDLONG;
359 else if (typeName == nsSchemaAtoms::sShort_atom) {
360 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_SHORT;
362 else if (typeName == nsSchemaAtoms::sUnsignedShort_atom) {
363 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_UNSIGNEDSHORT;
365 else if (typeName == nsSchemaAtoms::sDecimal_atom) {
366 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DECIMAL;
368 else if (typeName == nsSchemaAtoms::sFloat_atom) {
369 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_FLOAT;
371 else if (typeName == nsSchemaAtoms::sDouble_atom) {
372 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DOUBLE;
374 else if (typeName == nsSchemaAtoms::sBoolean_atom) {
375 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN;
377 else if (typeName == nsSchemaAtoms::sTime_atom) {
378 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_TIME;
380 else if (typeName == nsSchemaAtoms::sDateTime_atom) {
381 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATETIME;
383 else if (typeName == nsSchemaAtoms::sDuration_atom) {
384 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DURATION;
386 else if (typeName == nsSchemaAtoms::sDate_atom) {
387 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_DATE;
389 else if (typeName == nsSchemaAtoms::sGMonth_atom) {
390 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTH;
392 else if (typeName == nsSchemaAtoms::sGYear_atom) {
393 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEAR;
395 else if (typeName == nsSchemaAtoms::sGYearMonth_atom) {
396 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GYEARMONTH;
398 else if (typeName == nsSchemaAtoms::sGDay_atom) {
399 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GDAY;
401 else if (typeName == nsSchemaAtoms::sGMonthDay_atom) {
402 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_GMONTHDAY;
404 else if (typeName == nsSchemaAtoms::sName_atom) {
405 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NAME;
407 else if (typeName == nsSchemaAtoms::sQName_atom) {
408 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_QNAME;
410 else if (typeName == nsSchemaAtoms::sNCName_atom) {
411 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NCNAME;
413 else if (typeName == nsSchemaAtoms::sAnyURI_atom) {
414 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ANYURI;
416 else if (typeName == nsSchemaAtoms::sLanguage_atom) {
417 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_LANGUAGE;
419 else if (typeName == nsSchemaAtoms::sID_atom) {
420 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ID;
422 else if (typeName == nsSchemaAtoms::sIDREF_atom) {
423 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREF;
425 else if (typeName == nsSchemaAtoms::sIDREFS_atom) {
426 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_IDREFS;
428 else if (typeName == nsSchemaAtoms::sENTITY_atom) {
429 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITY;
431 else if (typeName == nsSchemaAtoms::sENTITIES_atom) {
432 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_ENTITIES;
434 else if (typeName == nsSchemaAtoms::sNOTATION_atom) {
435 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NOTATION;
437 else if (typeName == nsSchemaAtoms::sNMTOKEN_atom) {
438 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKEN;
440 else if (typeName == nsSchemaAtoms::sNMTOKENS_atom) {
441 typeVal = nsISchemaBuiltinType::BUILTIN_TYPE_NMTOKENS;
443 else {
444 NS_ERROR("Unknown builtin type");
445 return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
448 nsCOMPtr<nsISchemaType> builtin = new nsSchemaBuiltinType(typeVal);
449 if (!builtin) {
450 return NS_ERROR_OUT_OF_MEMORY;
453 mBuiltinTypesHash.Put(aName, builtin);
454 builtin.swap(*aType);
457 return NS_OK;
460 nsresult
461 nsBuiltinSchemaCollection::GetSOAPType(const nsAString& aName,
462 const nsAString& aNamespace,
463 nsISchemaType** aType)
465 nsresult rv = NS_OK;
467 if (!mSOAPTypeHash.Get(aName, aType)) {
468 if (aName.EqualsLiteral("Array")) {
469 nsCOMPtr<nsISchemaType> anyType;
470 rv = GetBuiltinType(NS_LITERAL_STRING("anyType"),
471 NS_LITERAL_STRING(NS_SCHEMA_2001_NAMESPACE),
472 getter_AddRefs(anyType));
473 if (NS_FAILED(rv)) {
474 return rv;
477 nsSOAPArray* array = new nsSOAPArray(anyType);
478 if (!array) {
479 return NS_ERROR_OUT_OF_MEMORY;
482 mSOAPTypeHash.Put(aName, array);
484 *aType = array;
485 NS_ADDREF(*aType);
487 else if (aName.EqualsLiteral("arrayType")) {
488 nsSOAPArrayType* arrayType = new nsSOAPArrayType();
489 if (!arrayType) {
490 return NS_ERROR_OUT_OF_MEMORY;
493 mSOAPTypeHash.Put(aName, arrayType);
495 *aType = arrayType;
496 NS_ADDREF(*aType);
498 else {
499 rv = NS_ERROR_SCHEMA_UNKNOWN_TYPE;
503 return rv;
506 ////////////////////////////////////////////////////////////
508 // nsSchemaLoader implementation
510 ////////////////////////////////////////////////////////////
512 nsSchemaLoader::nsSchemaLoader()
514 mBuiltinCollection = do_GetService(NS_BUILTINSCHEMACOLLECTION_CONTRACTID);
517 nsresult
518 nsSchemaLoader::Init()
520 return mSchemas.Init() ? NS_OK : NS_ERROR_FAILURE;
523 NS_IMPL_ISUPPORTS2_CI(nsSchemaLoader,
524 nsISchemaLoader,
525 nsISchemaCollection)
528 /* nsISchema getSchema (in AString targetNamespace); */
529 NS_IMETHODIMP
530 nsSchemaLoader::GetSchema(const nsAString & targetNamespace,
531 nsISchema ** aResult)
533 NS_ENSURE_ARG_POINTER(aResult);
535 return mSchemas.Get(targetNamespace, aResult) ? NS_OK :
536 NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
539 /* nsISchemaElement getElement (in AString name, in AString namespace); */
540 NS_IMETHODIMP
541 nsSchemaLoader::GetElement(const nsAString & aName,
542 const nsAString & aNamespace,
543 nsISchemaElement **_retval)
545 nsCOMPtr<nsISchema> schema;
546 nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
547 if (NS_FAILED(rv)) {
548 return rv;
551 return schema->GetElementByName(aName, _retval);
554 /* nsISchemaAttribute getAttribute (in AString name, in AString namespace); */
555 NS_IMETHODIMP
556 nsSchemaLoader::GetAttribute(const nsAString & aName,
557 const nsAString & aNamespace,
558 nsISchemaAttribute **_retval)
560 nsCOMPtr<nsISchema> schema;
561 nsresult rv = GetSchema(aNamespace, getter_AddRefs(schema));
562 if (NS_FAILED(rv)) {
563 return rv;
566 return schema->GetAttributeByName(aName, _retval);
569 /* nsISchemaType getType (in AString name, in AString namespace); */
570 NS_IMETHODIMP
571 nsSchemaLoader::GetType(const nsAString & aName,
572 const nsAString & aNamespace,
573 nsISchemaType **_retval)
575 nsresult rv = NS_OK;
577 if (IsSchemaNamespace(aNamespace) || IsSOAPNamespace(aNamespace)) {
578 rv = mBuiltinCollection->GetType(aName, aNamespace, _retval);
580 if (NS_FAILED(rv)) {
581 nsAutoString errorMsg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
582 errorMsg.AppendLiteral("Failure processing schema: cannot get schema type \"");
583 errorMsg.Append(aName);
584 errorMsg.AppendLiteral("\"");
585 NS_ERROR(NS_ConvertUTF16toUTF8(errorMsg).get());
587 return rv;
590 return NS_OK;
593 nsCOMPtr<nsISchema> schema;
594 rv = GetSchema(aNamespace, getter_AddRefs(schema));
595 if (NS_FAILED(rv)) {
596 return rv;
599 rv = schema->GetTypeByName(aName, _retval);
601 if (NS_FAILED(rv)) {
602 nsAutoString msg(NS_LITERAL_STRING("nsSchemaLoader::GetType: "));
603 msg.AppendLiteral("Failure processing schema: ");
604 msg.AppendLiteral("cannot get schema type \"");
605 msg.Append(aName);
606 msg.AppendLiteral("\"");
607 NS_ERROR(NS_ConvertUTF16toUTF8(msg).get());
609 return rv;
612 return NS_OK;
615 nsresult
616 nsSchemaLoader::GetResolvedURI(const nsAString& aSchemaURI,
617 const char* aMethod,
618 nsIURI** aURI)
620 nsresult rv;
621 nsCOMPtr<nsIXPCNativeCallContext> cc;
622 nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
623 if(NS_SUCCEEDED(rv)) {
624 rv = xpc->GetCurrentNativeCallContext(getter_AddRefs(cc));
627 if (NS_SUCCEEDED(rv) && cc) {
628 JSContext* cx;
629 rv = cc->GetJSContext(&cx);
630 if (NS_FAILED(rv)) return rv;
632 nsCOMPtr<nsIScriptSecurityManager> secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
633 if (NS_FAILED(rv)) return rv;
635 nsCOMPtr<nsIURI> baseURI;
636 nsCOMPtr<nsIPrincipal> principal;
637 rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal));
638 if (NS_SUCCEEDED(rv)) {
639 principal->GetURI(getter_AddRefs(baseURI));
642 rv = NS_NewURI(aURI, aSchemaURI, nsnull, baseURI);
643 if (NS_FAILED(rv)) return rv;
645 rv = secMan->CheckLoadURIFromScript(cx, *aURI);
646 if (NS_FAILED(rv))
648 // Security check failed. The above call set a JS exception. The
649 // following lines ensure that the exception is propagated.
650 cc->SetExceptionWasThrown(PR_TRUE);
651 return rv;
654 else {
655 rv = NS_NewURI(aURI, aSchemaURI, nsnull);
656 if (NS_FAILED(rv)) return rv;
659 return NS_OK;
662 /* nsISchema load (in AString schemaURI); */
663 NS_IMETHODIMP
664 nsSchemaLoader::Load(const nsAString& schemaURI,
665 nsISchema **_retval)
667 NS_ENSURE_ARG_POINTER(_retval);
669 nsCOMPtr<nsIDOMDocument> document;
670 nsresult rv = GetDocumentFromURI(schemaURI, getter_AddRefs(document));
671 NS_ENSURE_SUCCESS(rv, rv);
673 if (!document)
674 return NS_ERROR_SCHEMA_LOADING_ERROR;
676 nsCOMPtr<nsIDOMElement> element;
677 document->GetDocumentElement(getter_AddRefs(element));
678 if (element) {
679 //XXXTelemac TODO Have an error handler there instead or nsnull
680 rv = ProcessSchemaElement(element, nsnull, _retval);
682 else {
683 rv = NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
686 return rv;
689 /* void loadAsync (in AString schemaURI, in nsISchemaLoadListener listener); */
690 NS_IMETHODIMP
691 nsSchemaLoader::LoadAsync(const nsAString& schemaURI,
692 nsISchemaLoadListener *aListener)
694 NS_ENSURE_ARG(aListener);
696 nsCOMPtr<nsIURI> resolvedURI;
697 nsresult rv = GetResolvedURI(schemaURI, "loadAsync", getter_AddRefs(resolvedURI));
698 if (NS_FAILED(rv)) {
699 return rv;
701 nsCAutoString spec;
702 resolvedURI->GetSpec(spec);
704 nsCOMPtr<nsIXMLHttpRequest> request(do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv));
705 if (!request) {
706 return rv;
709 const nsAString& empty = EmptyString();
710 rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_TRUE, empty,
711 empty);
712 if (NS_FAILED(rv)) {
713 return rv;
716 // Force the mimetype of the returned stream to be xml.
717 rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
718 if (NS_FAILED(rv)) {
719 return rv;
722 nsCOMPtr<nsIDOMEventListener> listener;
723 LoadListener* listenerInst = new LoadListener(this, aListener, request);
724 if (!listenerInst) {
725 return NS_ERROR_OUT_OF_MEMORY;
727 listener = listenerInst;
729 nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(request));
730 if (!target) {
731 return NS_ERROR_UNEXPECTED;
734 rv = target->AddEventListener(NS_LITERAL_STRING("load"),
735 listener, PR_FALSE);
736 if (NS_FAILED(rv)) {
737 return rv;
740 rv = target->AddEventListener(NS_LITERAL_STRING("error"),
741 listener, PR_FALSE);
742 if (NS_FAILED(rv)) {
743 return rv;
746 // The listener keeps the request alive until its complete
747 rv = request->Send(nsnull);
749 return rv;
752 static const char* kSchemaNamespaces[] = {NS_SCHEMA_1999_NAMESPACE,
753 NS_SCHEMA_2001_NAMESPACE};
754 static PRUint32 kSchemaNamespacesLength = sizeof(kSchemaNamespaces) / sizeof(const char*);
756 /* nsISchema processSchemaElement (in nsIDOMElement element, in nsIWebServiceErrorHandler aErrorHandler); */
757 NS_IMETHODIMP
758 nsSchemaLoader::ProcessSchemaElement(nsIDOMElement* aElement,
759 nsIWebServiceErrorHandler* aErrorHandler,
760 nsISchema **aResult)
762 NS_ENSURE_ARG(aElement);
763 NS_ENSURE_ARG_POINTER(aResult);
765 nsRefPtr<nsSchema> schemaInst = new nsSchema(this, aElement);
766 if (!schemaInst) {
767 return NS_ERROR_OUT_OF_MEMORY;
770 nsresult rv = schemaInst->Init();
771 NS_ENSURE_SUCCESS(rv, rv);
773 nsAutoString targetNamespace;
774 schemaInst->GetTargetNamespace(targetNamespace);
776 nsISchema * os;
777 if (mSchemas.Get(targetNamespace, &os)) {
778 *aResult = os;
779 return NS_OK;
782 nsChildElementIterator iterator(aElement,
783 kSchemaNamespaces, kSchemaNamespacesLength);
784 nsCOMPtr<nsIDOMElement> childElement;
785 nsCOMPtr<nsIAtom> tagName;
787 // For now, ignore the following
788 // annotations
789 // redefine
790 // notation
791 // identity-constraint elements
793 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
794 getter_AddRefs(tagName))) &&
795 childElement) {
796 if (tagName == nsSchemaAtoms::sElement_atom) {
797 nsCOMPtr<nsISchemaElement> schemaElement;
798 rv = ProcessElement(aErrorHandler, schemaInst, childElement,
799 getter_AddRefs(schemaElement));
800 if (NS_SUCCEEDED(rv)) {
801 rv = schemaInst->AddElement(schemaElement);
804 else if (tagName == nsSchemaAtoms::sComplexType_atom) {
805 nsCOMPtr<nsISchemaComplexType> complexType;
806 rv = ProcessComplexType(aErrorHandler, schemaInst, childElement,
807 getter_AddRefs(complexType));
808 if (NS_SUCCEEDED(rv)) {
809 rv = schemaInst->AddType(complexType);
812 else if (tagName == nsSchemaAtoms::sSimpleType_atom) {
813 nsCOMPtr<nsISchemaSimpleType> simpleType;
814 rv = ProcessSimpleType(aErrorHandler, schemaInst, childElement,
815 getter_AddRefs(simpleType));
816 if (NS_SUCCEEDED(rv)) {
817 rv = schemaInst->AddType(simpleType);
820 else if (tagName == nsSchemaAtoms::sAttribute_atom) {
821 nsCOMPtr<nsISchemaAttribute> attribute;
822 rv = ProcessAttribute(aErrorHandler, schemaInst, childElement,
823 getter_AddRefs(attribute));
824 if (NS_SUCCEEDED(rv)) {
825 rv = schemaInst->AddAttribute(attribute);
828 else if (tagName == nsSchemaAtoms::sAttributeGroup_atom) {
829 nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
830 rv = ProcessAttributeGroup(aErrorHandler, schemaInst, childElement,
831 getter_AddRefs(attributeGroup));
832 if (NS_SUCCEEDED(rv)) {
833 rv = schemaInst->AddAttributeGroup(attributeGroup);
836 else if (tagName == nsSchemaAtoms::sModelGroup_atom) {
837 nsCOMPtr<nsISchemaModelGroup> modelGroup;
838 rv = ProcessModelGroup(aErrorHandler, schemaInst, childElement,
839 tagName, nsnull, getter_AddRefs(modelGroup));
840 if (NS_SUCCEEDED(rv)) {
841 rv = schemaInst->AddModelGroup(modelGroup);
844 else if (tagName == nsSchemaAtoms::sInclude_atom ||
845 tagName == nsSchemaAtoms::sImport_atom) {
846 /* Mixing the handling of <include> and <import> as they are very similar,
847 other than a few requirements regarding namespaces.
849 http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-include
850 If we include a schema, it must either
851 (a) have the same targetNamespace as the including schema document or
852 (b) no targetNamespace at all
854 http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-import
855 When importing a schema, it must either
856 (a) if namespace is defined, then namespace == imported
857 targetNamespace
858 (b) if namespace is not defined, then imported schema must NOT
859 have a targetNamespace
861 If the uri to load doesn't resolve, it isn't a error. It is if its an
862 invalid XML document or not a schema file
865 NS_NAMED_LITERAL_STRING(schemaLocationStr, "schemaLocation");
867 nsAutoString schemalocation;
868 childElement->GetAttribute(schemaLocationStr, schemalocation);
870 // if empty, skip it
871 if (schemalocation.IsEmpty())
872 continue;
874 nsCOMPtr<nsIIOService> ios = do_GetIOService();
875 NS_ENSURE_STATE(ios);
877 nsCOMPtr<nsIDOMDocument> document;
878 aElement->GetOwnerDocument(getter_AddRefs(document));
880 nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
881 NS_ENSURE_STATE(doc);
883 nsCOMPtr<nsIURI> uri;
885 rv = NS_NewURI(getter_AddRefs(uri),
886 NS_ConvertUTF16toUTF8(schemalocation),
887 doc->GetDocumentCharacterSet().get(),
888 doc->GetDocumentURI());
889 NS_ENSURE_SUCCESS(rv, rv);
890 NS_ENSURE_STATE(uri);
892 // since we could be going cross-domain, make sure we can load it by doing
893 // a principal same origin check.
895 // get the base document's principal
896 nsIPrincipal *basePrincipal = doc->NodePrincipal();
897 NS_ENSURE_STATE(basePrincipal);
899 // check the security manager and do a same original check on the principal
900 nsCOMPtr<nsIScriptSecurityManager> secMan =
901 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
902 NS_ENSURE_STATE(secMan);
904 // get a principal for the uri we are testing
905 nsCOMPtr<nsIPrincipal> testPrincipal;
906 rv = secMan->GetCodebasePrincipal(uri, getter_AddRefs(testPrincipal));
907 NS_ENSURE_SUCCESS(rv, rv);
909 rv = secMan->CheckSameOriginPrincipal(basePrincipal, testPrincipal);
910 // if not allowed, continue onwards
911 if (NS_FAILED(rv))
912 continue;
914 // get the url
915 nsCAutoString spec;
916 uri->GetSpec(spec);
918 nsCOMPtr<nsIDOMDocument> includedDocument;
919 rv = GetDocumentFromURI(NS_ConvertUTF8toUTF16(spec),
920 getter_AddRefs(includedDocument));
921 NS_ENSURE_SUCCESS(rv, rv);
923 // if no document, it is an error
924 NS_ENSURE_STATE(includedDocument);
926 // get the document element - it should be a xsd:schema
927 nsCOMPtr<nsIDOMElement> element;
928 includedDocument->GetDocumentElement(getter_AddRefs(element));
930 nsAutoString localName, nsUri;
931 element->GetLocalName(localName);
932 element->GetNamespaceURI(nsUri);
934 PRBool correctNamespace = PR_FALSE;
935 PRUint32 i;
936 for (i = 0; i < kSchemaNamespacesLength; i++) {
937 if (nsUri.Equals(NS_ConvertASCIItoUTF16(kSchemaNamespaces[i]))) {
938 correctNamespace = PR_TRUE;
939 break;
943 if (!correctNamespace || !localName.EqualsLiteral("schema")) {
944 // not a valid schema file
945 return NS_ERROR_SCHEMA_NOT_SCHEMA_ELEMENT;
948 // XXX: check the target namespace requirements
950 // If <import>, simply call self to do all the heavy lifting
951 if (tagName == nsSchemaAtoms::sImport_atom) {
952 rv = ProcessSchemaElement(element, nsnull, aResult);
953 NS_ENSURE_SUCCESS(rv, rv);
954 continue;
957 // import/append all elements in the included file to our schema element
958 nsCOMPtr<nsIDOMDocument> ownerDoc;
959 rv = childElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
960 NS_ENSURE_SUCCESS(rv, rv);
961 NS_ENSURE_STATE(ownerDoc);
963 nsCOMPtr<nsIDOMNode> tmpNode, importedNode, dummy;
964 element->GetFirstChild(getter_AddRefs(tmpNode));
966 // get the child element's next sibling so we have something to insert
967 // before while we are appending to the current schema document
968 unsigned short nodeType;
969 nsCOMPtr<nsIDOMNode> nextSibling;
970 childElement->GetNextSibling(getter_AddRefs(nextSibling));
972 while (tmpNode) {
973 tmpNode->GetNodeType(&nodeType);
975 if (nodeType == nsIDOMNode::ELEMENT_NODE) {
976 rv = ownerDoc->ImportNode(tmpNode, PR_TRUE,
977 getter_AddRefs(importedNode));
978 NS_ENSURE_SUCCESS(rv, rv);
980 // InsertBefore can deal with a null nextSibling (will append)
981 rv = aElement->InsertBefore(importedNode, nextSibling,
982 getter_AddRefs(dummy));
983 NS_ENSURE_SUCCESS(rv, rv);
986 tmpNode->GetNextSibling(getter_AddRefs(dummy));
987 tmpNode = dummy;
990 // we twidle the iterator (reset), making sure to point it at the right
991 // place. We do this because the iterator takes a snapshot the DOMList,
992 // so we tell it to reinit itself and then reset it to the original index.
993 PRUint32 index = iterator.GetCurrentIndex();
994 iterator.SetElement(aElement);
995 iterator.Reset(index);
996 } else if (tagName != nsSchemaAtoms::sAnnotation_atom &&
997 tagName != nsSchemaAtoms::sRedefine_atom &&
998 tagName != nsSchemaAtoms::sNotation_atom) {
999 // if it is none of these, unexpected element.
1000 nsAutoString elementName;
1001 nsresult rc = aElement->GetTagName(elementName);
1002 NS_ENSURE_SUCCESS(rc, rc);
1004 nsAutoString errorMsg;
1005 errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
1006 errorMsg.Append(elementName);
1007 errorMsg.AppendLiteral("\" in <schema .../>");
1009 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1011 return NS_ERROR_UNEXPECTED;
1014 if (NS_FAILED(rv)) {
1015 nsAutoString errorMsg;
1016 errorMsg.AppendLiteral("Failure processing schema");
1017 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1019 return rv;
1023 // We need to add this schema into the schema collection because resolving
1024 // forward references may require resolving types with namespace prefixes,
1025 // which could easily point back at this schema file.
1026 mSchemas.Put(targetNamespace, schemaInst);
1028 // Resolve all forward references
1029 rv = schemaInst->Resolve(aErrorHandler);
1030 if (NS_FAILED(rv)) {
1031 return rv;
1034 NS_ADDREF(*aResult = schemaInst);
1036 return NS_OK;
1039 PRBool
1040 ParseQualifiedName(nsIDOMElement* aContext,
1041 const nsAString& aQualifiedName,
1042 nsAString& aPrefix,
1043 nsAString& aLocalName,
1044 nsAString& aNamespaceURI)
1046 nsReadingIterator<PRUnichar> pos, begin, end;
1048 aQualifiedName.BeginReading(begin);
1049 aQualifiedName.EndReading(end);
1050 pos = begin;
1052 if (FindCharInReadable(PRUnichar(':'), pos, end)) {
1053 CopyUnicodeTo(begin, pos, aPrefix);
1054 CopyUnicodeTo(++pos, end, aLocalName);
1056 else {
1057 CopyUnicodeTo(begin, end, aLocalName);
1060 nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(aContext));
1062 return node->LookupNamespaceURI(aPrefix, aNamespaceURI);
1065 nsresult
1066 nsSchemaLoader::GetNewOrUsedType(nsSchema* aSchema,
1067 nsIDOMElement* aContext,
1068 const nsAString& aTypeName,
1069 nsISchemaType** aType)
1071 nsresult rv = NS_OK;
1072 nsAutoString prefix, localName, namespaceURI;
1074 // See if there's a prefix and get the
1075 // namespace associated with the prefix
1076 rv = ParseQualifiedName(aContext, aTypeName, prefix,
1077 localName, namespaceURI);
1078 if (!prefix.IsEmpty() && NS_FAILED(rv)) {
1079 // Unknown prefix
1080 return NS_ERROR_SCHEMA_UNKNOWN_PREFIX;
1083 *aType = nsnull;
1084 nsAutoString targetNamespace;
1085 aSchema->GetTargetNamespace(targetNamespace);
1086 if (namespaceURI.IsEmpty() || namespaceURI.Equals(targetNamespace)) {
1087 // It's a local type
1088 rv = aSchema->GetTypeByName(localName, aType);
1090 else {
1091 rv = GetType(localName, namespaceURI, aType);
1092 if (!*aType) {
1093 return NS_ERROR_SCHEMA_UNKNOWN_TARGET_NAMESPACE;
1097 // If we didn't get a type, we need to create a placeholder
1098 if (NS_SUCCEEDED(rv) && !*aType) {
1099 nsSchemaTypePlaceholder* placeholder = new nsSchemaTypePlaceholder(aSchema,
1100 localName);
1101 if (!placeholder) {
1102 return NS_ERROR_OUT_OF_MEMORY;
1104 *aType = placeholder;
1105 NS_ADDREF(*aType);
1108 return rv;
1112 * @param aErrorHandler Error handler (in).
1113 * @param aSchema Schema in which is the element, not null (in).
1114 * @param aElement DOM element <element .../>, not null (in).
1115 * @param aSchemaElement Schema element from processing DOM element (out).
1117 nsresult
1118 nsSchemaLoader::ProcessElement(nsIWebServiceErrorHandler* aErrorHandler,
1119 nsSchema* aSchema,
1120 nsIDOMElement* aElement,
1121 nsISchemaElement** aSchemaElement)
1123 nsresult rv = NS_OK;
1125 nsCOMPtr<nsISchemaElement> schemaElement;
1126 PRUint32 minOccurs, maxOccurs;
1127 GetMinAndMax(aElement, &minOccurs, &maxOccurs);
1129 // See if it's a reference or an actual element declaration
1130 nsAutoString ref;
1131 aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
1132 if (!ref.IsEmpty()) {
1133 nsSchemaElementRef* elementRef;
1134 nsAutoString refNS;
1136 // need to handle ns:type
1137 rv = ParseNameAndNS(ref, aElement, ref, refNS);
1138 NS_ENSURE_SUCCESS(rv, rv);
1140 elementRef = new nsSchemaElementRef(aSchema, ref, refNS);
1141 if (!elementRef) {
1142 return NS_ERROR_OUT_OF_MEMORY;
1144 schemaElement = elementRef;
1146 elementRef->SetMinOccurs(minOccurs);
1147 elementRef->SetMaxOccurs(maxOccurs);
1149 else {
1150 nsAutoString value;
1151 nsSchemaElement* elementInst;
1152 const nsAString& empty = EmptyString();
1154 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("name"), value);
1156 if (NS_FAILED(rv)) {
1157 nsresult rc = aElement->GetTagName(value);
1158 NS_ENSURE_SUCCESS(rc, rc);
1160 nsAutoString errorMsg;
1161 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1162 errorMsg.AppendLiteral("attribute \"name\" of element \"");
1163 errorMsg.Append(value);
1164 errorMsg.AppendLiteral("\"");
1166 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1168 return rv;
1171 value.Trim(" \r\n\t");
1172 elementInst = new nsSchemaElement(aSchema, value);
1173 if (!elementInst) {
1174 return NS_ERROR_OUT_OF_MEMORY;
1176 schemaElement = elementInst;
1178 elementInst->SetMinOccurs(minOccurs);
1179 elementInst->SetMaxOccurs(maxOccurs);
1181 nsAutoString defaultValue, fixedValue;
1182 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("default"),
1183 defaultValue);
1184 if (NS_FAILED(rv)) {
1185 nsresult rc = aElement->GetTagName(value);
1186 NS_ENSURE_SUCCESS(rc, rc);
1188 nsAutoString errorMsg;
1189 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1190 errorMsg.AppendLiteral("attribute \"default\" of element \"");
1191 errorMsg.Append(value);
1192 errorMsg.AppendLiteral("\"");
1194 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1196 return rv;
1199 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("fixed"),
1200 fixedValue);
1201 if (NS_FAILED(rv)) {
1202 nsresult rc = aElement->GetTagName(value);
1203 NS_ENSURE_SUCCESS(rc, rc);
1205 nsAutoString errorMsg;
1206 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1207 errorMsg.AppendLiteral("attribute \"fixed\" of element \"");
1208 errorMsg.Append(value);
1209 errorMsg.AppendLiteral("\"");
1211 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1213 return rv;
1216 elementInst->SetConstraints(defaultValue, fixedValue);
1218 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("nillable"), value);
1219 if (NS_FAILED(rv)) {
1220 nsresult rc = aElement->GetTagName(value);
1221 NS_ENSURE_SUCCESS(rc, rc);
1223 nsAutoString errorMsg;
1224 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1225 errorMsg.AppendLiteral("attribute \"nillable\" of element \"");
1226 errorMsg.Append(value);
1227 errorMsg.AppendLiteral("\"");
1229 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1231 return rv;
1233 value.Trim(" \r\n\t");
1235 PRInt32 flags = 0;
1236 if (value.EqualsLiteral("true"))
1237 flags |= nsSchemaElement::NILLABLE;
1239 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("abstract"), value);
1240 if (NS_FAILED(rv)) {
1241 nsresult rc = aElement->GetTagName(value);
1242 NS_ENSURE_SUCCESS(rc, rc);
1244 nsAutoString errorMsg;
1245 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1246 errorMsg.AppendLiteral("attribute \"abstract\" of element \"");
1247 errorMsg.Append(value);
1248 errorMsg.AppendLiteral("\"");
1250 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1252 return rv;
1254 value.Trim(" \r\n\t");
1256 if (value.EqualsLiteral("true"))
1257 flags |= nsSchemaElement::ABSTRACT;
1259 nsCOMPtr<nsIDOMNode> parent;
1260 rv = aElement->GetParentNode(getter_AddRefs(parent));
1261 if (NS_FAILED(rv))
1262 return rv;
1263 parent->GetLocalName(value);
1265 // Check if the schema element's targetNamespace applies to <element>.
1266 // Note: If the <element> element information item has <schema> as its
1267 // parent,then the actual value of the targetNamespace is that of the
1268 // parent <schema> element information item, or absent if there is
1269 // none. Otherwise if the <element> element information item has
1270 // <schema> element as an ancestor then if "form" is present and its actual
1271 // value is qualified, or if "form" is absent and the actual value of
1272 // elementFormDefault on the <schema> ancestor is qualified, then the
1273 // actual value of the targetNamespace [attribute] is that of the ancestor
1274 // <schema> element information item, or absent if there is none.
1275 if (value.EqualsLiteral("schema")) {
1276 flags |= nsSchemaElement::FORM_QUALIFIED;
1278 else {
1279 rv = aElement->GetAttributeNS(empty, NS_LITERAL_STRING("form"),
1280 value);
1281 if (NS_FAILED(rv)) {
1282 nsAutoString errorMsg;
1283 errorMsg.AppendLiteral("Failure processing schema element, cannot get ");
1284 errorMsg.AppendLiteral("attribute \"form\" of element \"");
1285 errorMsg.Append(value);
1286 errorMsg.AppendLiteral("\"");
1288 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1290 return rv;
1292 value.Trim(" \r\n\t");
1293 if (value.IsEmpty()) {
1294 if (aSchema->IsElementFormQualified()) {
1295 flags |= nsSchemaElement::FORM_QUALIFIED;
1297 else {
1298 flags &= ~nsSchemaElement::FORM_QUALIFIED;
1301 else if (value.EqualsLiteral("qualified")) {
1302 flags |= nsSchemaElement::FORM_QUALIFIED;
1304 else {
1305 flags &= ~nsSchemaElement::FORM_QUALIFIED;
1309 elementInst->SetFlags(flags);
1311 nsCOMPtr<nsISchemaType> schemaType;
1312 nsAutoString typeStr;
1313 aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
1314 if (!typeStr.IsEmpty()) {
1315 rv = GetNewOrUsedType(aSchema, aElement, typeStr,
1316 getter_AddRefs(schemaType));
1317 if (NS_FAILED(rv)) {
1318 nsAutoString errorMsg;
1319 errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
1320 errorMsg.Append(typeStr);
1321 errorMsg.AppendLiteral("\"");
1323 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1325 return rv;
1328 // Look for the type as a child of the element
1329 else {
1330 nsChildElementIterator iterator(aElement,
1331 kSchemaNamespaces,
1332 kSchemaNamespacesLength);
1333 nsCOMPtr<nsIDOMElement> childElement;
1334 nsCOMPtr<nsIAtom> tagName;
1336 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1337 getter_AddRefs(tagName))) &&
1338 childElement) {
1339 if (tagName == nsSchemaAtoms::sSimpleType_atom) {
1340 nsCOMPtr<nsISchemaSimpleType> simpleType;
1342 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
1343 getter_AddRefs(simpleType));
1344 if (NS_FAILED(rv)) {
1345 return rv;
1347 schemaType = simpleType;
1348 break;
1350 else if (tagName == nsSchemaAtoms::sComplexType_atom) {
1351 nsCOMPtr<nsISchemaComplexType> complexType;
1353 rv = ProcessComplexType(aErrorHandler, aSchema, childElement,
1354 getter_AddRefs(complexType));
1355 if (NS_FAILED(rv)) {
1356 return rv;
1358 schemaType = complexType;
1359 break;
1364 if (!schemaType) {
1365 nsAutoString ns;
1366 aElement->GetNamespaceURI(ns);
1367 rv = GetType(NS_LITERAL_STRING("anyType"),
1369 getter_AddRefs(schemaType));
1370 if (NS_FAILED(rv)) {
1371 nsAutoString errorMsg;
1372 errorMsg.AppendLiteral("Failure processing schema, cannot find \'anyType\' ");
1373 errorMsg.AppendLiteral("placeholder type in namespace \"");
1374 errorMsg.Append(ns);
1375 errorMsg.AppendLiteral("\"");
1377 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1379 return rv;
1383 rv = elementInst->SetType(schemaType);
1384 if (NS_FAILED(rv)) {
1385 return rv;
1389 *aSchemaElement = schemaElement;
1390 NS_ADDREF(*aSchemaElement);
1392 return NS_OK;
1396 * Handle <complexType ...>
1398 * @param aErrorHandler Webservice error handler.
1399 * @param aSchema Owning schema (in)
1400 * @param aElement <complexType> element (in)
1401 * @param aComplexType Schema complex type built from |aElement|
1403 nsresult
1404 nsSchemaLoader::ProcessComplexType(nsIWebServiceErrorHandler* aErrorHandler,
1405 nsSchema* aSchema,
1406 nsIDOMElement* aElement,
1407 nsISchemaComplexType** aComplexType)
1409 nsresult rv = NS_OK;
1410 nsCOMPtr<nsISchemaComplexType> complexType;
1412 nsAutoString abstract, name;
1413 aElement->GetAttribute(NS_LITERAL_STRING("abstract"), abstract);
1414 aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
1416 nsSchemaComplexType* typeInst;
1417 typeInst = new nsSchemaComplexType(aSchema, name,
1418 abstract.EqualsLiteral("true"));
1419 if (!typeInst) {
1420 return NS_ERROR_OUT_OF_MEMORY;
1422 complexType = typeInst;
1424 rv = typeInst->Init();
1425 NS_ENSURE_SUCCESS(rv, rv);
1427 nsChildElementIterator iterator(aElement,
1428 kSchemaNamespaces,
1429 kSchemaNamespacesLength);
1430 nsCOMPtr<nsIDOMElement> childElement;
1431 nsCOMPtr<nsIAtom> tagName;
1433 PRUint16 contentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
1434 PRUint16 derivation = nsISchemaComplexType::DERIVATION_SELF_CONTAINED;
1435 nsCOMPtr<nsISchemaType> baseType;
1436 nsCOMPtr<nsISchemaModelGroup> modelGroup;
1438 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1439 getter_AddRefs(tagName))) &&
1440 childElement) {
1441 if (tagName == nsSchemaAtoms::sSimpleContent_atom) {
1442 contentModel = nsISchemaComplexType::CONTENT_MODEL_SIMPLE;
1444 rv = ProcessSimpleContent(aErrorHandler, aSchema, childElement, typeInst,
1445 &derivation, getter_AddRefs(baseType));
1446 break;
1449 if (tagName == nsSchemaAtoms::sComplexContent_atom) {
1450 rv = ProcessComplexContent(aErrorHandler, aSchema, childElement, typeInst,
1451 &contentModel, &derivation,
1452 getter_AddRefs(baseType));
1453 break;
1456 if (tagName == nsSchemaAtoms::sModelGroup_atom ||
1457 tagName == nsSchemaAtoms::sAll_atom ||
1458 tagName == nsSchemaAtoms::sChoice_atom ||
1459 tagName == nsSchemaAtoms::sSequence_atom ||
1460 tagName == nsSchemaAtoms::sAttribute_atom ||
1461 tagName == nsSchemaAtoms::sAttributeGroup_atom ||
1462 tagName == nsSchemaAtoms::sAnyAttribute_atom) {
1463 rv = ProcessComplexTypeBody(aErrorHandler, aSchema,
1464 aElement, typeInst, nsnull,
1465 &contentModel);
1466 break;
1469 if (tagName == nsSchemaAtoms::sAnnotation_atom) {
1470 // XXX: skipping for now
1472 else {
1473 // Unexpected schema element
1474 nsAutoString elementName;
1475 rv = aElement->GetTagName(elementName);
1476 NS_ENSURE_SUCCESS(rv, rv);
1477 rv = NS_ERROR_UNEXPECTED;
1479 nsAutoString errorMsg;
1480 errorMsg.AppendLiteral("Failure processing schema, unexpected element \"");
1481 errorMsg.Append(elementName);
1482 errorMsg.AppendLiteral("\" in <complexType />, should be <simpleContent .../>");
1483 errorMsg.AppendLiteral(", <complexContent ../>, <annotation .../>");
1485 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1487 break;
1491 if (NS_FAILED(rv)) {
1492 return rv;
1495 nsAutoString mixed;
1496 aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
1497 if (mixed.EqualsLiteral("true")) {
1498 contentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
1501 typeInst->SetContentModel(contentModel);
1502 typeInst->SetDerivation(derivation, baseType);
1504 *aComplexType = complexType;
1505 NS_ADDREF(*aComplexType);
1507 return NS_OK;
1510 void
1511 nsSchemaLoader::ConstructArrayName(nsISchemaType* aType,
1512 nsAString& aName)
1514 nsAutoString typeName;
1516 aType->GetName(typeName);
1517 aName.Assign(NS_LITERAL_STRING("ArrayOf") + typeName);
1520 nsresult
1521 nsSchemaLoader::ParseDimensions(nsSchema* aSchema,
1522 nsIDOMElement* aAttrElement,
1523 const nsAString& aStr,
1524 nsISchemaType* aBaseType,
1525 nsISchemaType** aArrayType,
1526 PRUint32* aDimension)
1528 nsReadingIterator<PRUnichar> iter, done_reading;
1529 aStr.BeginReading(iter);
1530 aStr.EndReading(done_reading);
1532 PRUint32 dimension = 1;
1533 PRUnichar uc = *iter++;
1534 if (uc != PRUnichar('[')) {
1535 return NS_ERROR_UNEXPECTED;
1538 while (iter != done_reading) {
1539 uc = *iter++;
1540 if (uc == PRUnichar(',')) {
1541 dimension++;
1543 else if (uc == PRUnichar(']')) {
1544 break;
1547 *aDimension = dimension;
1549 while ((iter != done_reading) && (*iter == PRUnichar(' '))) {
1550 ++iter;
1553 // If there's still more to go, then create an array type
1554 // based on the base and continue to parse
1555 if ((iter != done_reading) && (*iter == PRUnichar('['))) {
1556 nsAutoString name;
1557 nsCOMPtr<nsISchemaType> myArrayType;
1558 PRUint32 myDimension;
1560 nsresult rv = ParseDimensions(aSchema, aAttrElement,
1561 nsDependentSubstring(iter, done_reading),
1562 aBaseType, getter_AddRefs(myArrayType),
1563 &myDimension);
1564 if (NS_FAILED(rv)) {
1565 return rv;
1568 ConstructArrayName(myArrayType, name);
1569 nsSchemaComplexType* typeInst = new nsSchemaComplexType(aSchema,
1570 name,
1571 PR_FALSE);
1572 if (!typeInst) {
1573 return NS_ERROR_OUT_OF_MEMORY;
1575 nsCOMPtr<nsISchemaComplexType> complexType = typeInst;
1577 rv = typeInst->Init();
1578 NS_ENSURE_SUCCESS(rv, rv);
1580 nsCOMPtr<nsISchemaType> soapArray;
1581 rv = GetType(NS_LITERAL_STRING("Array"),
1582 NS_LITERAL_STRING(NS_SOAP_1_2_ENCODING_NAMESPACE),
1583 getter_AddRefs(soapArray));
1584 if (NS_FAILED(rv)) {
1585 return rv;
1588 typeInst->SetContentModel(nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY);
1589 typeInst->SetDerivation(nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX,
1590 soapArray);
1591 typeInst->SetArrayInfo(myArrayType, myDimension);
1593 *aArrayType = typeInst;
1595 else {
1596 *aArrayType = aBaseType;
1598 NS_ADDREF(*aArrayType);
1600 return NS_OK;
1603 nsresult
1604 nsSchemaLoader::ParseArrayType(nsSchema* aSchema,
1605 nsIDOMElement* aAttrElement,
1606 const nsAString& aStr,
1607 nsISchemaType** aType,
1608 PRUint32* aDimension)
1610 PRInt32 offset;
1612 offset = aStr.FindChar(PRUnichar('['));
1613 if (offset == -1) {
1614 return NS_ERROR_SCHEMA_UNKNOWN_TYPE;
1616 nsDependentSubstring typeStr(aStr, 0, offset);
1618 nsCOMPtr<nsISchemaType> type;
1619 nsresult rv = GetNewOrUsedType(aSchema, aAttrElement, typeStr,
1620 getter_AddRefs(type));
1621 if (NS_FAILED(rv)) {
1622 return rv;
1625 nsDependentSubstring dimensionStr(aStr, offset,
1626 aStr.Length() - offset);
1627 return ParseDimensions(aSchema, aAttrElement, dimensionStr, type,
1628 aType, aDimension);
1632 nsresult
1633 nsSchemaLoader::ProcessComplexTypeBody(nsIWebServiceErrorHandler* aErrorHandler,
1634 nsSchema* aSchema,
1635 nsIDOMElement* aElement,
1636 nsSchemaComplexType* aComplexType,
1637 nsSchemaModelGroup* aSequence,
1638 PRUint16* aContentModel)
1640 nsresult rv = NS_OK;
1641 nsChildElementIterator iterator(aElement,
1642 kSchemaNamespaces,
1643 kSchemaNamespacesLength);
1644 nsCOMPtr<nsIDOMElement> childElement;
1645 nsCOMPtr<nsIAtom> tagName;
1647 *aContentModel = nsISchemaComplexType::CONTENT_MODEL_EMPTY;
1649 nsCOMPtr<nsISchemaModelGroup> modelGroup;
1651 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1652 getter_AddRefs(tagName))) &&
1653 childElement) {
1654 if ((tagName == nsSchemaAtoms::sModelGroup_atom) ||
1655 (tagName == nsSchemaAtoms::sAll_atom) ||
1656 (tagName == nsSchemaAtoms::sChoice_atom) ||
1657 (tagName == nsSchemaAtoms::sSequence_atom)) {
1659 if (modelGroup) {
1660 // We shouldn't already have a model group
1661 nsAutoString elementName;
1662 nsresult rv = childElement->GetTagName(elementName);
1663 NS_ENSURE_SUCCESS(rv, rv);
1665 nsAutoString errorMsg;
1666 errorMsg.AppendLiteral("Failure processing schema, must have ");
1667 errorMsg.AppendLiteral("model group in <complexType .../>, ");
1668 errorMsg.AppendLiteral("unexpected element \"");
1669 errorMsg.Append(elementName);
1670 errorMsg.AppendLiteral("\"");
1672 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
1674 return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
1677 rv = ProcessModelGroup(aErrorHandler, aSchema,
1678 childElement, tagName,
1679 aSequence, getter_AddRefs(modelGroup));
1680 if (NS_FAILED(rv)) {
1681 return rv;
1684 PRUint32 particleCount;
1685 modelGroup->GetParticleCount(&particleCount);
1686 if (particleCount) {
1687 *aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
1689 else {
1690 PRUint16 compositor;
1691 modelGroup->GetCompositor(&compositor);
1693 PRUint32 minOccurs;
1694 modelGroup->GetMinOccurs(&minOccurs);
1696 if ((compositor == nsISchemaModelGroup::COMPOSITOR_CHOICE) &&
1697 (minOccurs > 0)) {
1698 *aContentModel = nsISchemaComplexType::CONTENT_MODEL_ELEMENT_ONLY;
1702 if (aSequence) {
1703 // Check if we were collapsed
1704 if (modelGroup.get() != static_cast<nsISchemaModelGroup*>(aSequence)) {
1705 rv = aSequence->AddParticle(modelGroup);
1708 else {
1709 rv = aComplexType->SetModelGroup(modelGroup);
1711 if (NS_FAILED(rv)) {
1712 return rv;
1715 else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
1716 (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
1717 (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
1718 nsCOMPtr<nsISchemaAttributeComponent> attribute;
1720 rv = ProcessAttributeComponent(aErrorHandler, aSchema,
1721 childElement, tagName,
1722 getter_AddRefs(attribute));
1723 if (NS_FAILED(rv)) {
1724 return rv;
1727 rv = aComplexType->AddAttribute(attribute);
1728 if (NS_FAILED(rv)) {
1729 nsAutoString elementName;
1730 nsAutoString attributeName;
1731 nsresult rc = childElement->GetTagName(elementName);
1732 NS_ENSURE_SUCCESS(rc, rc);
1734 rc = attribute->GetName(attributeName);
1735 NS_ENSURE_SUCCESS(rc, rc);
1737 nsAutoString errorMsg;
1738 errorMsg.AppendLiteral("Failure processing schema, cannot process attribute \"");
1739 errorMsg.Append(attributeName);
1740 errorMsg.AppendLiteral("\" of element \"");
1741 errorMsg.Append(elementName);
1742 errorMsg.AppendLiteral("\"");
1744 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1746 return rv;
1749 // XXX WSDL ugliness making itself into schemas. Hopefully this
1750 // mechanism for specifying an array type in schemas will die
1751 // when the Schema WG address qualified names in attribute
1752 // default values.
1753 if (tagName == nsSchemaAtoms::sAttribute_atom) {
1754 #define NS_WSDL_NAMESPACE "http://schemas.xmlsoap.org/wsdl/"
1755 nsAutoString arrayType;
1756 childElement->GetAttributeNS(NS_LITERAL_STRING(NS_WSDL_NAMESPACE),
1757 NS_LITERAL_STRING("arrayType"),
1758 arrayType);
1759 if (!arrayType.IsEmpty()) {
1760 nsCOMPtr<nsISchemaType> arraySchemaType;
1761 PRUint32 arrayDimension;
1762 rv = ParseArrayType(aSchema,
1763 childElement,
1764 arrayType,
1765 getter_AddRefs(arraySchemaType),
1766 &arrayDimension);
1767 if (NS_FAILED(rv)) {
1768 nsAutoString errorMsg;
1769 errorMsg.AppendLiteral("Failure processing schema, ");
1770 errorMsg.AppendLiteral("cannot process array type \"");
1771 errorMsg.Append(arrayType);
1772 errorMsg.AppendLiteral("\"");
1774 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1776 return rv;
1779 rv = aComplexType->SetArrayInfo(arraySchemaType, arrayDimension);
1780 if (NS_FAILED(rv)) {
1781 nsAutoString errorMsg;
1782 errorMsg.AppendLiteral("Failure processing schema, cannot set ");
1783 errorMsg.AppendLiteral("array information for array type \"");
1784 errorMsg.Append(arrayType);
1785 errorMsg.AppendLiteral("\"");
1787 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1789 return rv;
1796 return rv;
1799 nsresult
1800 nsSchemaLoader::ProcessSimpleContent(nsIWebServiceErrorHandler* aErrorHandler,
1801 nsSchema* aSchema,
1802 nsIDOMElement* aElement,
1803 nsSchemaComplexType* aComplexType,
1804 PRUint16* aDerivation,
1805 nsISchemaType** aBaseType)
1807 nsresult rv = NS_OK;
1809 nsCOMPtr<nsISchemaType> baseType;
1811 nsChildElementIterator iterator(aElement,
1812 kSchemaNamespaces,
1813 kSchemaNamespacesLength);
1814 nsCOMPtr<nsIDOMElement> childElement;
1815 nsCOMPtr<nsIAtom> tagName;
1817 // A simpleContent element must have children
1818 if (!iterator.HasChildNodes()) {
1819 nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
1820 errorMsg.AppendLiteral("<simpleContent .../> invalid structure, should contains ");
1821 errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
1823 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
1825 return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
1828 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
1829 getter_AddRefs(tagName))) &&
1830 childElement) {
1831 nsAutoString baseStr;
1832 if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
1833 (tagName == nsSchemaAtoms::sExtension_atom)) {
1834 childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
1835 if (baseStr.IsEmpty()) {
1836 nsAutoString elementName;
1837 rv = childElement->GetTagName(elementName);
1838 NS_ENSURE_SUCCESS(rv, rv);
1840 nsAutoString errorMsg;
1841 errorMsg.AppendLiteral("Failure processing schema, \"");
1842 errorMsg.Append(elementName);
1843 errorMsg.AppendLiteral("\" must have a \"base\" attribute in order ");
1844 errorMsg.AppendLiteral("to specify base type");
1846 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
1848 return NS_ERROR_SCHEMA_MISSING_TYPE;
1851 rv = GetNewOrUsedType(aSchema, childElement, baseStr,
1852 getter_AddRefs(baseType));
1853 if (NS_FAILED(rv)) {
1854 nsAutoString errorMsg;
1855 errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
1856 errorMsg.Append(baseStr);
1857 errorMsg.AppendLiteral("\"");
1859 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1861 return rv;
1864 nsCOMPtr<nsISchemaSimpleType> simpleBaseType;
1865 if (tagName == nsSchemaAtoms::sRestriction_atom) {
1866 *aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_SIMPLE;
1867 rv = ProcessSimpleContentRestriction(aErrorHandler, aSchema, childElement,
1868 aComplexType, baseType,
1869 getter_AddRefs(simpleBaseType));
1870 if (NS_FAILED(rv)) {
1871 return rv;
1874 else {
1875 *aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_SIMPLE;
1877 nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
1878 if (complexBaseType) {
1879 // Copy over the attributes from the base type
1880 // XXX Should really be cloning
1881 PRUint32 attrIndex, attrCount;
1882 complexBaseType->GetAttributeCount(&attrCount);
1884 for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
1885 nsCOMPtr<nsISchemaAttributeComponent> attribute;
1887 rv = complexBaseType->GetAttributeByIndex(attrIndex,
1888 getter_AddRefs(attribute));
1889 if (NS_FAILED(rv)) {
1890 nsAutoString errorMsg;
1891 errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
1892 errorMsg.AppendLiteral("attributes from base type \"");
1893 errorMsg.Append(baseStr);
1894 errorMsg.AppendLiteral("\"");
1896 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1898 return rv;
1901 rv = aComplexType->AddAttribute(attribute);
1902 if (NS_FAILED(rv)) {
1903 nsAutoString errorMsg;
1904 errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
1905 errorMsg.AppendLiteral("attributes from base type \"");
1906 errorMsg.Append(baseStr);
1907 errorMsg.AppendLiteral("\"");
1909 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
1911 return rv;
1916 rv = ProcessSimpleContentExtension(aErrorHandler, aSchema, childElement,
1917 aComplexType, baseType,
1918 getter_AddRefs(simpleBaseType));
1919 if (NS_FAILED(rv)) {
1920 return rv;
1924 if (simpleBaseType) {
1925 rv = aComplexType->SetSimpleBaseType(simpleBaseType);
1926 if (NS_FAILED(rv)) {
1927 return rv;
1930 break;
1934 *aBaseType = baseType;
1935 NS_IF_ADDREF(*aBaseType);
1937 return NS_OK;
1940 nsresult
1941 nsSchemaLoader::ProcessSimpleContentRestriction(nsIWebServiceErrorHandler* aErrorHandler,
1942 nsSchema* aSchema,
1943 nsIDOMElement* aElement,
1944 nsSchemaComplexType* aComplexType,
1945 nsISchemaType* aBaseType,
1946 nsISchemaSimpleType** aSimpleBaseType)
1948 nsresult rv = NS_OK;
1950 nsChildElementIterator iterator(aElement,
1951 kSchemaNamespaces,
1952 kSchemaNamespacesLength);
1953 nsCOMPtr<nsIDOMElement> childElement;
1954 nsCOMPtr<nsIAtom> tagName;
1956 nsSchemaRestrictionType* restrictionInst;
1957 nsCOMPtr<nsISchemaSimpleType> simpleBase;
1959 restrictionInst = new nsSchemaRestrictionType(aSchema, EmptyString());
1960 if (!restrictionInst) {
1961 return NS_ERROR_OUT_OF_MEMORY;
1963 simpleBase = restrictionInst;
1965 // The base type must actually be a complex type (which itself must
1966 // have a simple base type.
1967 nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
1968 if (!complexBase) {
1969 // if base type is a place holder, this is ok
1970 PRUint16 schemaType;
1971 rv = aBaseType->GetSchemaType(&schemaType);
1973 if (NS_SUCCEEDED(rv) && schemaType == nsISchemaType::SCHEMA_TYPE_PLACEHOLDER) {
1974 simpleBase = do_QueryInterface(aBaseType);
1975 } else {
1976 nsAutoString baseStr;
1977 rv = aBaseType->GetName(baseStr);
1978 NS_ENSURE_SUCCESS(rv, rv);
1980 nsAutoString errorMsg;
1981 errorMsg.AppendLiteral("Failure processing schema, base type \"");
1982 errorMsg.Append(baseStr);
1983 errorMsg.AppendLiteral("\" of restriction must be a complex type ");
1984 errorMsg.AppendLiteral("which itself must be based on a simple type");
1986 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
1988 return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
1990 } else {
1991 nsCOMPtr<nsISchemaSimpleType> parentSimpleBase;
1992 complexBase->GetSimpleBaseType(getter_AddRefs(parentSimpleBase));
1994 if (parentSimpleBase) {
1995 rv = restrictionInst->SetBaseType(parentSimpleBase);
1996 NS_ENSURE_SUCCESS(rv, rv);
2000 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2001 getter_AddRefs(tagName))) &&
2002 childElement) {
2003 if (tagName == nsSchemaAtoms::sSimpleType_atom) {
2004 nsCOMPtr<nsISchemaSimpleType> simpleType;
2006 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
2007 getter_AddRefs(simpleType));
2008 NS_ENSURE_SUCCESS(rv, rv);
2010 rv = restrictionInst->SetBaseType(simpleType);
2011 NS_ENSURE_SUCCESS(rv, rv);
2013 else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
2014 (tagName == nsSchemaAtoms::sMinInclusive_atom) ||
2015 (tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
2016 (tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
2017 (tagName == nsSchemaAtoms::sTotalDigits_atom) ||
2018 (tagName == nsSchemaAtoms::sFractionDigits_atom) ||
2019 (tagName == nsSchemaAtoms::sLength_atom) ||
2020 (tagName == nsSchemaAtoms::sMinLength_atom) ||
2021 (tagName == nsSchemaAtoms::sMaxLength_atom) ||
2022 (tagName == nsSchemaAtoms::sEnumeration_atom) ||
2023 (tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
2024 (tagName == nsSchemaAtoms::sPattern_atom)) {
2025 nsCOMPtr<nsISchemaFacet> facet;
2027 rv = ProcessFacet(aErrorHandler, aSchema, childElement,
2028 tagName, getter_AddRefs(facet));
2029 NS_ENSURE_SUCCESS(rv, rv);
2031 rv = restrictionInst->AddFacet(facet);
2032 NS_ENSURE_SUCCESS(rv, rv);
2034 else if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
2035 (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
2036 (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
2037 nsCOMPtr<nsISchemaAttributeComponent> attribute;
2039 rv = ProcessAttributeComponent(aErrorHandler, aSchema,
2040 childElement, tagName,
2041 getter_AddRefs(attribute));
2042 NS_ENSURE_SUCCESS(rv, rv);
2044 rv = aComplexType->AddAttribute(attribute);
2045 NS_ENSURE_SUCCESS(rv, rv);
2049 *aSimpleBaseType = simpleBase;
2050 NS_IF_ADDREF(*aSimpleBaseType);
2052 return NS_OK;
2055 nsresult
2056 nsSchemaLoader::ProcessSimpleContentExtension(nsIWebServiceErrorHandler* aErrorHandler,
2057 nsSchema* aSchema,
2058 nsIDOMElement* aElement,
2059 nsSchemaComplexType* aComplexType,
2060 nsISchemaType* aBaseType,
2061 nsISchemaSimpleType** aSimpleBaseType)
2063 nsresult rv = NS_OK;
2065 nsChildElementIterator iterator(aElement,
2066 kSchemaNamespaces,
2067 kSchemaNamespacesLength);
2068 nsCOMPtr<nsIDOMElement> childElement;
2069 nsCOMPtr<nsIAtom> tagName;
2071 // If the base type is a complex type, it must itself have a simple
2072 // base type
2073 nsCOMPtr<nsISchemaComplexType> complexBase = do_QueryInterface(aBaseType);
2074 if (complexBase) {
2075 complexBase->GetSimpleBaseType(aSimpleBaseType);
2077 else {
2078 aBaseType->QueryInterface(NS_GET_IID(nsISchemaSimpleType),
2079 (void**)aSimpleBaseType);
2082 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2083 getter_AddRefs(tagName))) &&
2084 childElement) {
2085 if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
2086 (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
2087 (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
2088 nsCOMPtr<nsISchemaAttributeComponent> attribute;
2090 rv = ProcessAttributeComponent(aErrorHandler, aSchema,
2091 childElement, tagName,
2092 getter_AddRefs(attribute));
2093 if (NS_FAILED(rv)) {
2094 return rv;
2097 rv = aComplexType->AddAttribute(attribute);
2098 if (NS_FAILED(rv)) {
2099 return rv;
2104 return NS_OK;
2107 nsresult
2108 nsSchemaLoader::ProcessComplexContent(nsIWebServiceErrorHandler* aErrorHandler,
2109 nsSchema* aSchema,
2110 nsIDOMElement* aElement,
2111 nsSchemaComplexType* aComplexType,
2112 PRUint16* aContentModel,
2113 PRUint16* aDerivation,
2114 nsISchemaType** aBaseType)
2116 nsresult rv = NS_OK;
2118 nsCOMPtr<nsISchemaType> baseType;
2119 nsChildElementIterator iterator(aElement,
2120 kSchemaNamespaces,
2121 kSchemaNamespacesLength);
2122 nsCOMPtr<nsIDOMElement> childElement;
2123 nsCOMPtr<nsIAtom> tagName;
2125 // A complexContent element must have children
2126 if (!iterator.HasChildNodes()) {
2127 nsAutoString errorMsg(NS_LITERAL_STRING("Failure processing schema, "));
2128 errorMsg.AppendLiteral("<complexContent .../> must contains ");
2129 errorMsg.AppendLiteral("<restriction .../> or <extension .../>");
2130 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_STRUCTURE, errorMsg);
2132 return NS_ERROR_SCHEMA_INVALID_STRUCTURE;
2135 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2136 getter_AddRefs(tagName))) &&
2137 childElement) {
2138 nsAutoString baseStr;
2139 if ((tagName == nsSchemaAtoms::sRestriction_atom) ||
2140 (tagName == nsSchemaAtoms::sExtension_atom)) {
2141 childElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
2142 if (baseStr.IsEmpty()) {
2143 nsAutoString errorMsg;
2144 errorMsg.AppendLiteral("Failure processing schema, ");
2146 if (tagName == nsSchemaAtoms::sRestriction_atom) {
2147 errorMsg.AppendLiteral("restriction");
2149 else {
2150 errorMsg.AppendLiteral("extension");
2153 errorMsg.AppendLiteral(" must have a \"base\" attribute in order to ");
2154 errorMsg.AppendLiteral("specify base type");
2156 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
2158 return NS_ERROR_SCHEMA_MISSING_TYPE;
2161 rv = GetNewOrUsedType(aSchema, childElement, baseStr,
2162 getter_AddRefs(baseType));
2163 if (NS_FAILED(rv)) {
2164 nsAutoString errorMsg;
2165 errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
2166 errorMsg.Append(baseStr);
2167 errorMsg.AppendLiteral("\"");
2169 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2171 return rv;
2174 nsCOMPtr<nsISchemaComplexType> complexBaseType(do_QueryInterface(baseType));
2176 if (tagName == nsSchemaAtoms::sRestriction_atom) {
2177 *aDerivation = nsISchemaComplexType::DERIVATION_RESTRICTION_COMPLEX;
2178 rv = ProcessComplexTypeBody(aErrorHandler, aSchema, childElement,
2179 aComplexType, nsnull, aContentModel);
2181 else {
2182 *aDerivation = nsISchemaComplexType::DERIVATION_EXTENSION_COMPLEX;
2184 nsCOMPtr<nsISchemaModelGroup> sequence;
2185 nsSchemaModelGroup* sequenceInst = nsnull;
2186 if (complexBaseType) {
2187 // XXX Should really be cloning
2188 nsCOMPtr<nsISchemaModelGroup> baseGroup;
2189 rv = complexBaseType->GetModelGroup(getter_AddRefs(baseGroup));
2190 if (NS_FAILED(rv)) {
2191 nsAutoString errorMsg;
2192 errorMsg.AppendLiteral("Failure processing schema, extension for type \"");
2193 errorMsg.Append(baseStr);
2194 errorMsg.AppendLiteral("\" does not contains any model group");
2195 errorMsg.AppendLiteral("such as <all>, <choice>, <sequence>, or <group>");
2197 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2199 return rv;
2202 if (baseGroup) {
2203 // Create a new model group that's going to be the a sequence
2204 // of the base model group and the content below
2205 sequenceInst = new nsSchemaModelGroup(aSchema, EmptyString());
2206 if (!sequenceInst) {
2207 return NS_ERROR_OUT_OF_MEMORY;
2209 sequence = sequenceInst;
2211 PRUint16 compositor;
2212 baseGroup->GetCompositor(&compositor);
2214 PRUint32 minOccurs, maxOccurs;
2215 baseGroup->GetMinOccurs(&minOccurs);
2216 baseGroup->GetMaxOccurs(&maxOccurs);
2218 // If the base group also a sequence, we can collapse the
2219 // two sequences.
2220 if ((compositor == nsISchemaModelGroup::COMPOSITOR_SEQUENCE) &&
2221 (minOccurs == 1) && (maxOccurs == 1)) {
2222 PRUint32 pIndex, pCount;
2223 baseGroup->GetParticleCount(&pCount);
2224 for (pIndex = 0; pIndex < pCount; pIndex++) {
2225 nsCOMPtr<nsISchemaParticle> particle;
2227 rv = baseGroup->GetParticle(pIndex, getter_AddRefs(particle));
2228 if (NS_FAILED(rv)) {
2229 nsAutoString errorMsg;
2230 errorMsg.AppendLiteral("Failure processing schema, failure ");
2231 errorMsg.AppendLiteral("processing model group for extension ");
2232 errorMsg.AppendLiteral("of type \"");
2233 errorMsg.Append(baseStr);
2234 errorMsg.AppendLiteral("\"");
2236 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2238 return rv;
2241 rv = sequenceInst->AddParticle(particle);
2242 if (NS_FAILED(rv)) {
2243 nsAutoString errorMsg;
2244 errorMsg.AppendLiteral("Failure processing schema, failure ");
2245 errorMsg.AppendLiteral("processing model group for extension ");
2246 errorMsg.AppendLiteral("of type \"");
2247 errorMsg.Append(baseStr);
2248 errorMsg.AppendLiteral("\"");
2250 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2252 return rv;
2256 else {
2257 sequenceInst->AddParticle(baseGroup);
2260 aComplexType->SetModelGroup(sequence);
2264 PRUint16 explicitContent;
2265 rv = ProcessComplexTypeBody(aErrorHandler, aSchema, childElement,
2266 aComplexType, sequenceInst,
2267 &explicitContent);
2268 if (NS_FAILED(rv)) {
2269 return rv;
2271 // If the explicit content is empty, get the content type
2272 // from the base
2273 if ((explicitContent == nsISchemaComplexType::CONTENT_MODEL_EMPTY) &&
2274 complexBaseType) {
2275 complexBaseType->GetContentModel(aContentModel);
2277 else {
2278 *aContentModel = explicitContent;
2282 // Copy over the attributes from the base type
2283 // XXX Should really be cloning
2284 if (complexBaseType) {
2285 PRUint32 attrIndex, attrCount;
2286 complexBaseType->GetAttributeCount(&attrCount);
2288 for (attrIndex = 0; attrIndex < attrCount; attrIndex++) {
2289 nsCOMPtr<nsISchemaAttributeComponent> attribute;
2291 rv = complexBaseType->GetAttributeByIndex(attrIndex,
2292 getter_AddRefs(attribute));
2293 if (NS_FAILED(rv)) {
2294 nsAutoString errorMsg;
2295 errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
2296 errorMsg.AppendLiteral("attributes from base type \"");
2297 errorMsg.Append(baseStr);
2298 errorMsg.AppendLiteral("\"");
2300 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2302 return rv;
2305 rv = aComplexType->AddAttribute(attribute);
2306 if (NS_FAILED(rv)) {
2307 nsAutoString errorMsg;
2308 errorMsg.AppendLiteral("Failure processing schema, cannot clone ");
2309 errorMsg.AppendLiteral("attributes from base type \"");
2310 errorMsg.Append(baseStr);
2311 errorMsg.AppendLiteral("\"");
2313 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2315 return rv;
2321 break;
2325 nsAutoString mixed;
2326 aElement->GetAttribute(NS_LITERAL_STRING("mixed"), mixed);
2327 if (mixed.EqualsLiteral("true")) {
2328 *aContentModel = nsISchemaComplexType::CONTENT_MODEL_MIXED;
2331 *aBaseType = baseType;
2332 NS_IF_ADDREF(*aBaseType);
2334 return NS_OK;
2337 nsresult
2338 nsSchemaLoader::ProcessSimpleType(nsIWebServiceErrorHandler* aErrorHandler,
2339 nsSchema* aSchema,
2340 nsIDOMElement* aElement,
2341 nsISchemaSimpleType** aSimpleType)
2343 nsresult rv = NS_OK;
2345 nsAutoString name;
2346 aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
2348 nsChildElementIterator iterator(aElement,
2349 kSchemaNamespaces,
2350 kSchemaNamespacesLength);
2351 nsCOMPtr<nsIDOMElement> childElement;
2352 nsCOMPtr<nsIAtom> tagName;
2354 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2355 getter_AddRefs(tagName))) &&
2356 childElement) {
2357 if (tagName == nsSchemaAtoms::sRestriction_atom) {
2358 rv = ProcessSimpleTypeRestriction(aErrorHandler, aSchema, childElement,
2359 name, aSimpleType);
2360 break;
2362 else if (tagName == nsSchemaAtoms::sList_atom) {
2363 rv = ProcessSimpleTypeList(aErrorHandler, aSchema, childElement,
2364 name, aSimpleType);
2365 break;
2367 else if (tagName == nsSchemaAtoms::sUnion_atom) {
2368 rv = ProcessSimpleTypeUnion(aErrorHandler, aSchema, childElement,
2369 name, aSimpleType);
2370 break;
2374 return rv;
2377 nsresult
2378 nsSchemaLoader::ProcessSimpleTypeRestriction(nsIWebServiceErrorHandler* aErrorHandler,
2379 nsSchema* aSchema,
2380 nsIDOMElement* aElement,
2381 const nsAString& aName,
2382 nsISchemaSimpleType** aSimpleType)
2384 nsresult rv = NS_OK;
2386 nsSchemaRestrictionType* restrictionInst;
2387 nsCOMPtr<nsISchemaSimpleType> restriction;
2389 restrictionInst = new nsSchemaRestrictionType(aSchema, aName);
2390 if (!restrictionInst) {
2391 return NS_ERROR_OUT_OF_MEMORY;
2393 restriction = restrictionInst;
2395 nsCOMPtr<nsISchemaType> baseType;
2396 nsAutoString baseStr;
2397 aElement->GetAttribute(NS_LITERAL_STRING("base"), baseStr);
2398 if (!baseStr.IsEmpty()) {
2399 rv = GetNewOrUsedType(aSchema, aElement, baseStr,
2400 getter_AddRefs(baseType));
2401 if (NS_FAILED(rv)) {
2402 nsAutoString errorMsg;
2403 errorMsg.AppendLiteral("Failure processing schema, unknown base type \"");
2404 errorMsg.Append(baseStr);
2405 errorMsg.AppendLiteral("\"");
2407 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2409 return rv;
2412 nsCOMPtr<nsISchemaSimpleType> simpleBase(do_QueryInterface(baseType));
2413 if (!simpleBase) {
2414 nsAutoString errorMsg;
2415 errorMsg.AppendLiteral("Failure processing schema, base type \"");
2416 errorMsg.Append(baseStr);
2417 errorMsg.AppendLiteral("\" should be a simple type");
2419 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
2421 return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
2423 rv = restrictionInst->SetBaseType(simpleBase);
2426 nsChildElementIterator iterator(aElement,
2427 kSchemaNamespaces,
2428 kSchemaNamespacesLength);
2429 nsCOMPtr<nsIDOMElement> childElement;
2430 nsCOMPtr<nsIAtom> tagName;
2432 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2433 getter_AddRefs(tagName))) &&
2434 childElement) {
2435 if ((tagName == nsSchemaAtoms::sSimpleType_atom) &&
2436 !baseType) {
2437 nsCOMPtr<nsISchemaSimpleType> simpleType;
2439 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
2440 getter_AddRefs(simpleType));
2441 if (NS_FAILED(rv)) {
2442 return rv;
2445 rv = restrictionInst->SetBaseType(simpleType);
2446 if (NS_FAILED(rv)) {
2447 return rv;
2449 baseType = simpleType;
2451 else if ((tagName == nsSchemaAtoms::sMinExclusive_atom) ||
2452 (tagName == nsSchemaAtoms::sMinInclusive_atom) ||
2453 (tagName == nsSchemaAtoms::sMaxExclusive_atom) ||
2454 (tagName == nsSchemaAtoms::sMaxInclusive_atom) ||
2455 (tagName == nsSchemaAtoms::sTotalDigits_atom) ||
2456 (tagName == nsSchemaAtoms::sFractionDigits_atom) ||
2457 (tagName == nsSchemaAtoms::sLength_atom) ||
2458 (tagName == nsSchemaAtoms::sMinLength_atom) ||
2459 (tagName == nsSchemaAtoms::sMaxLength_atom) ||
2460 (tagName == nsSchemaAtoms::sEnumeration_atom) ||
2461 (tagName == nsSchemaAtoms::sWhiteSpace_atom) ||
2462 (tagName == nsSchemaAtoms::sPattern_atom)) {
2463 nsCOMPtr<nsISchemaFacet> facet;
2465 rv = ProcessFacet(aErrorHandler, aSchema, childElement,
2466 tagName, getter_AddRefs(facet));
2467 if (NS_FAILED(rv)) {
2468 return rv;
2471 rv = restrictionInst->AddFacet(facet);
2472 if (NS_FAILED(rv)) {
2473 return rv;
2478 *aSimpleType = restriction;
2479 NS_ADDREF(*aSimpleType);
2481 return NS_OK;
2484 nsresult
2485 nsSchemaLoader::ProcessSimpleTypeList(nsIWebServiceErrorHandler* aErrorHandler,
2486 nsSchema* aSchema,
2487 nsIDOMElement* aElement,
2488 const nsAString& aName,
2489 nsISchemaSimpleType** aSimpleType)
2491 nsresult rv = NS_OK;
2493 nsSchemaListType* listInst;
2494 nsCOMPtr<nsISchemaSimpleType> list;
2496 listInst = new nsSchemaListType(aSchema, aName);
2497 if (!listInst) {
2498 return NS_ERROR_OUT_OF_MEMORY;
2500 list = listInst;
2502 nsAutoString itemTypeStr;
2503 aElement->GetAttribute(NS_LITERAL_STRING("itemType"), itemTypeStr);
2505 nsCOMPtr<nsISchemaSimpleType> itemType;
2506 if (!itemTypeStr.IsEmpty()) {
2507 nsCOMPtr<nsISchemaType> type;
2508 rv = GetNewOrUsedType(aSchema, aElement, itemTypeStr,
2509 getter_AddRefs(type));
2510 if (NS_FAILED(rv)) {
2511 nsAutoString errorMsg;
2512 errorMsg.AppendLiteral("Failure processing schema, unknown item type \"");
2513 errorMsg.Append(itemTypeStr);
2514 errorMsg.AppendLiteral("\"");
2516 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2518 return rv;
2521 itemType = do_QueryInterface(type);
2523 else {
2524 nsChildElementIterator iterator(aElement,
2525 kSchemaNamespaces,
2526 kSchemaNamespacesLength);
2527 nsCOMPtr<nsIDOMElement> childElement;
2528 nsCOMPtr<nsIAtom> tagName;
2530 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2531 getter_AddRefs(tagName))) &&
2532 childElement) {
2533 if (tagName == nsSchemaAtoms::sSimpleType_atom) {
2534 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
2535 getter_AddRefs(itemType));
2536 if (NS_FAILED(rv)) {
2537 return rv;
2539 break;
2544 if (!itemType) {
2545 nsAutoString errorMsg;
2546 errorMsg.AppendLiteral("Failure processing schema, no item type ");
2547 errorMsg.AppendLiteral("for simple type \"");
2548 errorMsg.Append(aName);
2549 errorMsg.AppendLiteral("\"");
2551 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_MISSING_TYPE, errorMsg);
2553 return NS_ERROR_SCHEMA_MISSING_TYPE;
2555 listInst->SetListType(itemType);
2557 *aSimpleType = list;
2558 NS_ADDREF(*aSimpleType);
2560 return NS_OK;
2563 nsresult
2564 nsSchemaLoader::ProcessSimpleTypeUnion(nsIWebServiceErrorHandler* aErrorHandler,
2565 nsSchema* aSchema,
2566 nsIDOMElement* aElement,
2567 const nsAString& aName,
2568 nsISchemaSimpleType** aSimpleType)
2570 nsresult rv = NS_OK;
2572 nsSchemaUnionType* unionInst;
2573 nsCOMPtr<nsISchemaSimpleType> unionType;
2575 unionInst = new nsSchemaUnionType(aSchema, aName);
2576 if (!unionInst) {
2577 return NS_ERROR_OUT_OF_MEMORY;
2579 unionType = unionInst;
2581 nsCOMPtr<nsISchemaSimpleType> memberType;
2582 nsAutoString memberTypes;
2583 aElement->GetAttribute(NS_LITERAL_STRING("memberTypes"), memberTypes);
2584 if (!memberTypes.IsEmpty()) {
2585 nsReadingIterator<PRUnichar> begin, end, tokenEnd;
2587 memberTypes.BeginReading(tokenEnd);
2588 memberTypes.EndReading(end);
2590 while (tokenEnd != end) {
2591 nsAutoString typeStr;
2592 begin = tokenEnd;
2593 if (FindCharInReadable(PRUnichar(' '), tokenEnd, end)) {
2594 CopyUnicodeTo(begin, tokenEnd, typeStr);
2595 ++tokenEnd;
2597 else {
2598 CopyUnicodeTo(begin, end, typeStr);
2601 nsCOMPtr<nsISchemaType> type;
2602 rv = GetNewOrUsedType(aSchema, aElement, typeStr,
2603 getter_AddRefs(type));
2604 if (NS_FAILED(rv)) {
2605 nsAutoString errorMsg;
2606 errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
2607 errorMsg.Append(typeStr);
2608 errorMsg.AppendLiteral("\"");
2610 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
2612 return rv;
2615 memberType = do_QueryInterface(type);
2616 if (!memberType) {
2617 nsAutoString errorMsg;
2618 errorMsg.AppendLiteral("Failure processing schema, invalid member type \"");
2619 errorMsg.Append(typeStr);
2620 errorMsg.AppendLiteral("\" for union about simple type \"");
2621 errorMsg.Append(aName);
2622 errorMsg.AppendLiteral("\"");
2624 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
2626 return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
2629 rv = unionInst->AddUnionType(memberType);
2630 if (NS_FAILED(rv)) {
2631 return rv;
2636 nsChildElementIterator iterator(aElement,
2637 kSchemaNamespaces,
2638 kSchemaNamespacesLength);
2639 nsCOMPtr<nsIDOMElement> childElement;
2640 nsCOMPtr<nsIAtom> tagName;
2642 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2643 getter_AddRefs(tagName))) &&
2644 childElement) {
2645 if (tagName == nsSchemaAtoms::sSimpleType_atom) {
2646 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
2647 getter_AddRefs(memberType));
2648 if (NS_FAILED(rv)) {
2649 return rv;
2652 rv = unionInst->AddUnionType(memberType);
2653 if (NS_FAILED(rv)) {
2654 return rv;
2659 *aSimpleType = unionType;
2660 NS_ADDREF(*aSimpleType);
2662 return NS_OK;
2665 nsresult
2666 nsSchemaLoader::ProcessModelGroup(nsIWebServiceErrorHandler* aErrorHandler,
2667 nsSchema* aSchema,
2668 nsIDOMElement* aElement,
2669 nsIAtom* aTagName,
2670 nsSchemaModelGroup* aParentSequence,
2671 nsISchemaModelGroup** aModelGroup)
2673 nsresult rv = NS_OK;
2675 nsCOMPtr<nsISchemaModelGroup> modelGroup;
2676 PRUint32 minOccurs, maxOccurs;
2677 GetMinAndMax(aElement, &minOccurs, &maxOccurs);
2679 // Check for a ref attribute
2680 nsAutoString ref, refNS;
2681 aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
2683 if ((aTagName == nsSchemaAtoms::sModelGroup_atom) &&
2684 !ref.IsEmpty()) {
2686 rv = ParseNameAndNS(ref, aElement, ref, refNS);
2687 NS_ENSURE_SUCCESS(rv, rv);
2689 nsSchemaModelGroupRef* modelGroupRef = new nsSchemaModelGroupRef(aSchema,
2690 ref,
2691 refNS);
2692 if (!modelGroupRef) {
2693 return NS_ERROR_OUT_OF_MEMORY;
2695 modelGroup = modelGroupRef;
2697 modelGroupRef->SetMinOccurs(minOccurs);
2698 modelGroupRef->SetMaxOccurs(maxOccurs);
2700 else {
2701 nsAutoString name;
2702 aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
2704 nsChildElementIterator iterator(aElement,
2705 kSchemaNamespaces,
2706 kSchemaNamespacesLength);
2707 nsCOMPtr<nsIDOMElement> childElement;
2708 nsCOMPtr<nsIAtom> tagName = aTagName;
2710 // If this is a group element, find the first compositor
2711 // child and continue with that.
2712 if (aTagName == nsSchemaAtoms::sModelGroup_atom) {
2713 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2714 getter_AddRefs(tagName))) &&
2715 childElement) {
2716 if ((tagName == nsSchemaAtoms::sAll_atom) ||
2717 (tagName == nsSchemaAtoms::sChoice_atom) ||
2718 (tagName == nsSchemaAtoms::sSequence_atom)) {
2719 iterator.SetElement(childElement);
2720 break;
2725 nsSchemaModelGroup* modelGroupInst;
2727 // If we have a parent sequence and we're a sequence that
2728 // only appears once, then collapse us.
2729 if (aParentSequence &&
2730 (tagName == nsSchemaAtoms::sSequence_atom) &&
2731 (minOccurs == 1) && (maxOccurs == 1)) {
2732 modelGroupInst = aParentSequence;
2733 modelGroup = modelGroupInst;
2735 else {
2736 modelGroupInst = new nsSchemaModelGroup(aSchema, name);
2737 if (!modelGroupInst) {
2738 return NS_ERROR_OUT_OF_MEMORY;
2740 modelGroup = modelGroupInst;
2742 modelGroupInst->SetMinOccurs(minOccurs);
2743 modelGroupInst->SetMaxOccurs(maxOccurs);
2746 if (tagName == nsSchemaAtoms::sAll_atom) {
2747 modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_ALL);
2749 else if (tagName == nsSchemaAtoms::sChoice_atom) {
2750 modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_CHOICE);
2752 else if (tagName == nsSchemaAtoms::sSequence_atom) {
2753 modelGroupInst->SetCompositor(nsISchemaModelGroup::COMPOSITOR_SEQUENCE);
2757 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2758 getter_AddRefs(tagName))) &&
2759 childElement) {
2760 if (tagName != nsSchemaAtoms::sAnnotation_atom) {
2761 nsCOMPtr<nsISchemaParticle> particle;
2763 rv = ProcessParticle(aErrorHandler, aSchema, childElement,
2764 tagName, getter_AddRefs(particle));
2765 if (NS_FAILED(rv)) {
2766 return rv;
2769 rv = modelGroupInst->AddParticle(particle);
2770 if (NS_FAILED(rv)) {
2771 return rv;
2777 *aModelGroup = modelGroup;
2778 NS_ADDREF(*aModelGroup);
2780 return NS_OK;
2783 nsresult
2784 nsSchemaLoader::ProcessParticle(nsIWebServiceErrorHandler* aErrorHandler,
2785 nsSchema* aSchema,
2786 nsIDOMElement* aElement,
2787 nsIAtom* aTagName,
2788 nsISchemaParticle** aParticle)
2790 nsresult rv;
2792 if (aTagName == nsSchemaAtoms::sElement_atom) {
2793 nsCOMPtr<nsISchemaElement> element;
2795 rv = ProcessElement(aErrorHandler, aSchema, aElement, getter_AddRefs(element));
2796 if (NS_FAILED(rv)) {
2797 return rv;
2799 *aParticle = element;
2800 NS_IF_ADDREF(*aParticle);
2802 else if ((aTagName == nsSchemaAtoms::sModelGroup_atom) ||
2803 (aTagName == nsSchemaAtoms::sChoice_atom) ||
2804 (aTagName == nsSchemaAtoms::sSequence_atom)) {
2805 nsCOMPtr<nsISchemaModelGroup> modelGroup;
2807 rv = ProcessModelGroup(aErrorHandler, aSchema, aElement,
2808 aTagName, nsnull, getter_AddRefs(modelGroup));
2809 if (NS_FAILED(rv)) {
2810 return rv;
2812 *aParticle = modelGroup;
2813 NS_IF_ADDREF(*aParticle);
2815 else if (aTagName == nsSchemaAtoms::sAny_atom) {
2817 nsCOMPtr<nsISchemaParticle> anyParticle;
2818 nsSchemaAnyParticle* anyParticleInst = new nsSchemaAnyParticle(aSchema);
2819 if (!anyParticleInst) {
2820 return NS_ERROR_OUT_OF_MEMORY;
2822 anyParticle = anyParticleInst;
2824 PRUint32 minOccurs, maxOccurs;
2825 GetMinAndMax(aElement, &minOccurs, &maxOccurs);
2826 anyParticleInst->SetMinOccurs(minOccurs);
2827 anyParticleInst->SetMaxOccurs(maxOccurs);
2829 PRUint16 process;
2830 GetProcess(aElement, &process);
2831 anyParticleInst->SetProcess(process);
2833 nsAutoString namespaceStr;
2834 aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
2835 anyParticleInst->SetNamespace(namespaceStr);
2837 *aParticle = anyParticle;
2838 NS_ADDREF(*aParticle);
2842 return NS_OK;
2845 nsresult
2846 nsSchemaLoader::ProcessAttributeComponent(nsIWebServiceErrorHandler* aErrorHandler,
2847 nsSchema* aSchema,
2848 nsIDOMElement* aElement,
2849 nsIAtom* aTagName,
2850 nsISchemaAttributeComponent** aAttribute)
2852 nsresult rv;
2854 if (aTagName == nsSchemaAtoms::sAttribute_atom) {
2855 nsCOMPtr<nsISchemaAttribute> attribute;
2857 rv = ProcessAttribute(aErrorHandler, aSchema, aElement,
2858 getter_AddRefs(attribute));
2859 if (NS_FAILED(rv)) {
2860 return rv;
2862 *aAttribute = attribute;
2863 NS_IF_ADDREF(*aAttribute);
2865 else if (aTagName == nsSchemaAtoms::sAttributeGroup_atom) {
2866 nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
2868 rv = ProcessAttributeGroup(aErrorHandler, aSchema, aElement,
2869 getter_AddRefs(attributeGroup));
2870 if (NS_FAILED(rv)) {
2871 return rv;
2873 *aAttribute = attributeGroup;
2874 NS_IF_ADDREF(*aAttribute);
2876 else if (aTagName == nsSchemaAtoms::sAnyAttribute_atom) {
2877 nsCOMPtr<nsISchemaAttributeComponent> anyAttribute;
2878 nsSchemaAnyAttribute* anyAttributeInst = new nsSchemaAnyAttribute(aSchema);
2879 if (!anyAttributeInst) {
2880 return NS_ERROR_OUT_OF_MEMORY;
2882 anyAttribute = anyAttributeInst;
2884 PRUint16 process;
2885 GetProcess(aElement, &process);
2886 anyAttributeInst->SetProcess(process);
2888 nsAutoString namespaceStr;
2889 aElement->GetAttribute(NS_LITERAL_STRING("namespace"), namespaceStr);
2890 anyAttributeInst->SetNamespace(namespaceStr);
2892 *aAttribute = anyAttribute;
2893 NS_ADDREF(*aAttribute);
2897 return NS_OK;
2900 nsresult
2901 nsSchemaLoader::ProcessAttribute(nsIWebServiceErrorHandler* aErrorHandler,
2902 nsSchema* aSchema,
2903 nsIDOMElement* aElement,
2904 nsISchemaAttribute** aAttribute)
2906 nsresult rv;
2908 nsCOMPtr<nsISchemaAttribute> attribute;
2910 nsAutoString defaultValue, fixedValue, formValue;
2911 aElement->GetAttribute(NS_LITERAL_STRING("default"), defaultValue);
2912 aElement->GetAttribute(NS_LITERAL_STRING("fixed"), fixedValue);
2913 aElement->GetAttribute(NS_LITERAL_STRING("form"), formValue);
2915 PRUint16 use;
2916 GetUse(aElement, &use);
2918 nsAutoString ref, refNS;
2919 aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
2920 if (!ref.IsEmpty()) {
2921 rv = ParseNameAndNS(ref, aElement, ref, refNS);
2922 NS_ENSURE_SUCCESS(rv, rv);
2924 nsSchemaAttributeRef* attributeRef = new nsSchemaAttributeRef(aSchema,
2925 ref, refNS);
2926 if (!attributeRef) {
2927 return NS_ERROR_OUT_OF_MEMORY;
2929 attribute = attributeRef;
2931 attributeRef->SetConstraints(defaultValue, fixedValue);
2932 attributeRef->SetUse(use);
2934 // set the qualified form
2935 if (formValue.EqualsLiteral("qualified")) {
2936 attributeRef->SetAttributeFormQualified(PR_TRUE);
2938 else if (formValue.EqualsLiteral("unqualified")) {
2939 attributeRef->SetAttributeFormQualified(PR_FALSE);
2941 else {
2942 // get default
2943 PRBool defaultvalue = aSchema->IsAttributeFormDefaultQualified();
2944 attributeRef->SetAttributeFormQualified(defaultvalue);
2947 else {
2948 nsAutoString name;
2949 aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
2951 nsSchemaAttribute* attributeInst = new nsSchemaAttribute(aSchema,
2952 name);
2953 if (!attributeInst) {
2954 return NS_ERROR_OUT_OF_MEMORY;
2956 attribute = attributeInst;
2958 attributeInst->SetConstraints(defaultValue, fixedValue);
2959 attributeInst->SetUse(use);
2961 // set the qualified form
2962 if (formValue.EqualsLiteral("qualified")) {
2963 attributeInst->SetAttributeFormQualified(PR_TRUE);
2965 else if (formValue.EqualsLiteral("unqualified")) {
2966 attributeInst->SetAttributeFormQualified(PR_FALSE);
2968 else {
2969 // get default
2970 PRBool defaultvalue = aSchema->IsAttributeFormDefaultQualified();
2971 attributeInst->SetAttributeFormQualified(defaultvalue);
2974 nsCOMPtr<nsISchemaSimpleType> simpleType;
2976 nsChildElementIterator iterator(aElement,
2977 kSchemaNamespaces,
2978 kSchemaNamespacesLength);
2979 nsCOMPtr<nsIDOMElement> childElement;
2980 nsCOMPtr<nsIAtom> tagName;
2982 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
2983 getter_AddRefs(tagName))) &&
2984 childElement) {
2985 if (tagName == nsSchemaAtoms::sSimpleType_atom) {
2986 rv = ProcessSimpleType(aErrorHandler, aSchema, childElement,
2987 getter_AddRefs(simpleType));
2988 if (NS_FAILED(rv)) {
2989 return rv;
2991 break;
2995 if (!simpleType) {
2996 nsAutoString typeStr;
2997 aElement->GetAttribute(NS_LITERAL_STRING("type"), typeStr);
2999 if (!typeStr.IsEmpty()) {
3000 nsCOMPtr<nsISchemaType> schemaType;
3001 rv = GetNewOrUsedType(aSchema, aElement, typeStr,
3002 getter_AddRefs(schemaType));
3003 if (NS_FAILED(rv)) {
3004 nsAutoString errorMsg;
3005 errorMsg.AppendLiteral("Failure processing schema, unknown type \"");
3006 errorMsg.Append(typeStr);
3007 errorMsg.AppendLiteral("\"");
3009 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
3011 return rv;
3014 simpleType = do_QueryInterface(schemaType);
3015 if (!simpleType) {
3016 nsAutoString errorMsg;
3017 errorMsg.AppendLiteral("Failure processing schema, invalid type \"");
3018 errorMsg.Append(typeStr);
3019 errorMsg.AppendLiteral("\" for attribute \"");
3020 errorMsg.Append(name);
3021 errorMsg.AppendLiteral("\"");
3023 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_INVALID_TYPE_USAGE, errorMsg);
3025 return NS_ERROR_SCHEMA_INVALID_TYPE_USAGE;
3030 attributeInst->SetType(simpleType);
3033 *aAttribute = attribute;
3034 NS_ADDREF(*aAttribute);
3036 return NS_OK;
3039 nsresult
3040 nsSchemaLoader::ProcessAttributeGroup(nsIWebServiceErrorHandler* aErrorHandler,
3041 nsSchema* aSchema,
3042 nsIDOMElement* aElement,
3043 nsISchemaAttributeGroup** aAttributeGroup)
3045 nsresult rv;
3047 nsCOMPtr<nsISchemaAttributeGroup> attributeGroup;
3049 nsAutoString ref, refNS;
3050 aElement->GetAttribute(NS_LITERAL_STRING("ref"), ref);
3052 if (!ref.IsEmpty()) {
3053 // need to handle ns:type
3054 rv = ParseNameAndNS(ref, aElement, ref, refNS);
3055 NS_ENSURE_SUCCESS(rv, rv);
3057 nsSchemaAttributeGroupRef* attrRef = new nsSchemaAttributeGroupRef(aSchema,
3058 ref,
3059 refNS);
3060 if (!attrRef) {
3061 return NS_ERROR_OUT_OF_MEMORY;
3063 attributeGroup = attrRef;
3065 else {
3066 nsAutoString name;
3067 aElement->GetAttribute(NS_LITERAL_STRING("name"), name);
3069 nsSchemaAttributeGroup* attrInst = new nsSchemaAttributeGroup(aSchema,
3070 name);
3071 if (!attrInst) {
3072 return NS_ERROR_OUT_OF_MEMORY;
3074 attributeGroup = attrInst;
3076 rv = attrInst->Init();
3077 NS_ENSURE_SUCCESS(rv, rv);
3079 nsChildElementIterator iterator(aElement,
3080 kSchemaNamespaces,
3081 kSchemaNamespacesLength);
3082 nsCOMPtr<nsIDOMElement> childElement;
3083 nsCOMPtr<nsIAtom> tagName;
3085 while (NS_SUCCEEDED(iterator.GetNextChild(getter_AddRefs(childElement),
3086 getter_AddRefs(tagName))) &&
3087 childElement) {
3088 if ((tagName == nsSchemaAtoms::sAttribute_atom) ||
3089 (tagName == nsSchemaAtoms::sAttributeGroup_atom) ||
3090 (tagName == nsSchemaAtoms::sAnyAttribute_atom)) {
3091 nsCOMPtr<nsISchemaAttributeComponent> attribute;
3093 rv = ProcessAttributeComponent(aErrorHandler, aSchema,
3094 childElement, tagName,
3095 getter_AddRefs(attribute));
3096 if (NS_FAILED(rv)) {
3097 return rv;
3100 rv = attrInst->AddAttribute(attribute);
3101 if (NS_FAILED(rv)) {
3102 return rv;
3108 *aAttributeGroup = attributeGroup;
3109 NS_ADDREF(*aAttributeGroup);
3111 return NS_OK;
3114 nsresult
3115 nsSchemaLoader::ProcessFacet(nsIWebServiceErrorHandler* aErrorHandler,
3116 nsSchema* aSchema,
3117 nsIDOMElement* aElement,
3118 nsIAtom* aTagName,
3119 nsISchemaFacet** aFacet)
3121 PRInt32 rv;
3123 nsCOMPtr<nsISchemaFacet> facet;
3124 nsSchemaFacet* facetInst = new nsSchemaFacet(aSchema);
3125 if (!facetInst) {
3126 return NS_ERROR_OUT_OF_MEMORY;
3128 facet = facetInst;
3130 PRUint16 facetType;
3131 if (aTagName == nsSchemaAtoms::sLength_atom) {
3132 facetType = nsISchemaFacet::FACET_TYPE_LENGTH;
3134 else if (aTagName == nsSchemaAtoms::sMinLength_atom) {
3135 facetType = nsISchemaFacet::FACET_TYPE_MINLENGTH;
3137 else if (aTagName == nsSchemaAtoms::sMaxLength_atom) {
3138 facetType = nsISchemaFacet::FACET_TYPE_MAXLENGTH;
3140 else if (aTagName == nsSchemaAtoms::sPattern_atom) {
3141 facetType = nsISchemaFacet::FACET_TYPE_PATTERN;
3143 else if (aTagName == nsSchemaAtoms::sEnumeration_atom) {
3144 facetType = nsISchemaFacet::FACET_TYPE_ENUMERATION;
3146 else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
3147 facetType = nsISchemaFacet::FACET_TYPE_WHITESPACE;
3149 else if (aTagName == nsSchemaAtoms::sMaxInclusive_atom) {
3150 facetType = nsISchemaFacet::FACET_TYPE_MAXINCLUSIVE;
3152 else if (aTagName == nsSchemaAtoms::sMinInclusive_atom) {
3153 facetType = nsISchemaFacet::FACET_TYPE_MININCLUSIVE;
3155 else if (aTagName == nsSchemaAtoms::sMaxExclusive_atom) {
3156 facetType = nsISchemaFacet::FACET_TYPE_MAXEXCLUSIVE;
3158 else if (aTagName == nsSchemaAtoms::sMinExclusive_atom) {
3159 facetType = nsISchemaFacet::FACET_TYPE_MINEXCLUSIVE;
3161 else if (aTagName == nsSchemaAtoms::sTotalDigits_atom) {
3162 facetType = nsISchemaFacet::FACET_TYPE_TOTALDIGITS;
3164 else if (aTagName == nsSchemaAtoms::sFractionDigits_atom) {
3165 facetType = nsISchemaFacet::FACET_TYPE_FRACTIONDIGITS;
3167 else {
3168 nsAutoString elementName;
3169 rv = aElement->GetTagName(elementName);
3170 NS_ENSURE_SUCCESS(rv, rv);
3172 nsAutoString errorMsg;
3173 errorMsg.AppendLiteral("Failure processing schema, unknown type of facet \"");
3174 errorMsg.Append(elementName);
3175 errorMsg.AppendLiteral("\"");
3177 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_UNEXPECTED, errorMsg);
3179 return NS_ERROR_UNEXPECTED;
3181 facetInst->SetFacetType(facetType);
3183 nsAutoString valueStr;
3184 aElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
3185 if (valueStr.IsEmpty()) {
3186 nsAutoString elementName;
3187 rv = aElement->GetTagName(elementName);
3188 NS_ENSURE_SUCCESS(rv, rv);
3190 rv = NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
3192 nsAutoString errorMsg;
3193 errorMsg.AppendLiteral("Failure processing schema, invalid empty value ");
3194 errorMsg.AppendLiteral("for facet \"");
3195 errorMsg.Append(elementName);
3196 errorMsg.AppendLiteral("\"");
3198 NS_SCHEMALOADER_FIRE_ERROR(rv, errorMsg);
3200 return rv;
3203 if ((aTagName == nsSchemaAtoms::sLength_atom) ||
3204 (aTagName == nsSchemaAtoms::sMinLength_atom) ||
3205 (aTagName == nsSchemaAtoms::sMaxLength_atom) ||
3206 (aTagName == nsSchemaAtoms::sTotalDigits_atom) ||
3207 (aTagName == nsSchemaAtoms::sFractionDigits_atom)) {
3208 PRInt32 intVal = valueStr.ToInteger(&rv);
3210 if (NS_FAILED(rv) ||
3211 (intVal < 0) ||
3212 ((aTagName == nsSchemaAtoms::sTotalDigits_atom) && (intVal == 0))) {
3213 nsAutoString elementName;
3214 rv = aElement->GetTagName(elementName);
3215 NS_ENSURE_SUCCESS(rv, rv);
3217 nsAutoString errorMsg;
3218 errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
3219 errorMsg.Append(elementName);
3220 errorMsg.AppendLiteral("\", <=0");
3222 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
3224 return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
3227 facetInst->SetUintValue((PRUint32)intVal);
3229 else if (aTagName == nsSchemaAtoms::sWhiteSpace_atom) {
3230 PRUint16 whiteSpaceVal;
3231 if (valueStr.EqualsLiteral("collapse")) {
3232 whiteSpaceVal = nsSchemaFacet::WHITESPACE_COLLAPSE;
3234 else if (valueStr.EqualsLiteral("preserve")) {
3235 whiteSpaceVal = nsSchemaFacet::WHITESPACE_PRESERVE;
3237 else if (valueStr.EqualsLiteral("replace")) {
3238 whiteSpaceVal = nsSchemaFacet::WHITESPACE_REPLACE;
3240 else {
3241 nsAutoString elementName;
3242 rv = aElement->GetTagName(elementName);
3243 NS_ENSURE_SUCCESS(rv, rv);
3245 nsAutoString errorMsg;
3246 errorMsg.AppendLiteral("Failure processing schema, invalid value for facet \"");
3247 errorMsg.Append(elementName);
3248 errorMsg.AppendLiteral("\", should be \"collapse\", \"preserve\" or \"replace\"");
3250 NS_SCHEMALOADER_FIRE_ERROR(NS_ERROR_SCHEMA_FACET_VALUE_ERROR, errorMsg);
3252 return NS_ERROR_SCHEMA_FACET_VALUE_ERROR;
3255 facetInst->SetWhitespaceValue(whiteSpaceVal);
3257 else {
3258 facetInst->SetValue(valueStr);
3261 nsAutoString isFixed;
3262 aElement->GetAttribute(NS_LITERAL_STRING("fixed"), isFixed);
3263 facetInst->SetIsFixed(isFixed.EqualsLiteral("true"));
3265 *aFacet = facet;
3266 NS_ADDREF(*aFacet);
3268 return NS_OK;
3271 void
3272 nsSchemaLoader::GetUse(nsIDOMElement* aElement,
3273 PRUint16* aUse)
3275 *aUse = nsISchemaAttribute::USE_OPTIONAL;
3277 nsAutoString use;
3278 aElement->GetAttribute(NS_LITERAL_STRING("use"), use);
3280 if (use.EqualsLiteral("prohibited")) {
3281 *aUse = nsISchemaAttribute::USE_PROHIBITED;
3283 else if (use.EqualsLiteral("required")) {
3284 *aUse = nsISchemaAttribute::USE_REQUIRED;
3288 void
3289 nsSchemaLoader::GetProcess(nsIDOMElement* aElement,
3290 PRUint16* aProcess)
3292 *aProcess = nsISchemaAnyParticle::PROCESS_STRICT;
3294 nsAutoString process;
3295 aElement->GetAttribute(NS_LITERAL_STRING("process"), process);
3297 if (process.EqualsLiteral("lax")) {
3298 *aProcess = nsISchemaAnyParticle::PROCESS_LAX;
3300 else if (process.EqualsLiteral("skip")) {
3301 *aProcess = nsISchemaAnyParticle::PROCESS_SKIP;
3305 void
3306 nsSchemaLoader::GetMinAndMax(nsIDOMElement* aElement,
3307 PRUint32* aMinOccurs,
3308 PRUint32* aMaxOccurs)
3310 *aMinOccurs = 1;
3311 *aMaxOccurs = 1;
3313 nsAutoString minStr, maxStr;
3314 aElement->GetAttribute(NS_LITERAL_STRING("minOccurs"), minStr);
3315 aElement->GetAttribute(NS_LITERAL_STRING("maxOccurs"), maxStr);
3317 PRInt32 rv;
3318 if (!minStr.IsEmpty()) {
3319 PRInt32 minVal = minStr.ToInteger(&rv);
3320 if (NS_SUCCEEDED(rv) && (minVal >= 0)) {
3321 *aMinOccurs = (PRUint32)minVal;
3325 if (!maxStr.IsEmpty()) {
3326 if (maxStr.EqualsLiteral("unbounded")) {
3327 *aMaxOccurs = nsISchemaParticle::OCCURRENCE_UNBOUNDED;
3329 else {
3330 PRInt32 maxVal = maxStr.ToInteger(&rv);
3331 if (NS_SUCCEEDED(rv) && (maxVal >= 0)) {
3332 *aMaxOccurs = (PRUint32)maxVal;
3338 nsresult
3339 nsSchemaLoader::ParseNameAndNS(const nsAString& aName, nsIDOMElement* aElement,
3340 nsAString& aTypeName, nsAString& aTypeNS)
3342 nsresult rv;
3343 nsCOMPtr<nsIParserService> parserService =
3344 do_GetService("@mozilla.org/parser/parser-service;1", &rv);
3345 NS_ENSURE_SUCCESS(rv, rv);
3347 const nsAFlatString& qName = PromiseFlatString(aName);
3348 const PRUnichar *colon;
3349 rv = parserService->CheckQName(qName, PR_TRUE, &colon);
3350 NS_ENSURE_SUCCESS(rv, rv);
3352 if (colon) {
3353 const PRUnichar* end;
3354 qName.EndReading(end);
3356 nsAutoString schemaTypePrefix;
3357 schemaTypePrefix.Assign(Substring(qName.get(), colon));
3358 aTypeName.Assign(Substring(colon + 1, end));
3360 nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aElement);
3361 NS_ENSURE_STATE(domNode3);
3363 // get the namespace url from the prefix
3364 rv = domNode3->LookupNamespaceURI(schemaTypePrefix, aTypeNS);
3365 NS_ENSURE_SUCCESS(rv, rv);
3368 return rv;
3371 nsresult
3372 nsSchemaLoader::GetDocumentFromURI(const nsAString& aUri,
3373 nsIDOMDocument** aDocument)
3375 *aDocument = nsnull;
3377 nsCOMPtr<nsIURI> resolvedURI;
3378 nsresult rv = GetResolvedURI(aUri, "load", getter_AddRefs(resolvedURI));
3379 NS_ENSURE_SUCCESS(rv, rv);
3381 nsCOMPtr<nsIXMLHttpRequest> request =
3382 do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
3383 NS_ENSURE_SUCCESS(rv, rv);
3385 nsCAutoString spec;
3386 resolvedURI->GetSpec(spec);
3388 const nsAString& empty = EmptyString();
3389 rv = request->OpenRequest(NS_LITERAL_CSTRING("GET"), spec, PR_FALSE, empty,
3390 empty);
3391 NS_ENSURE_SUCCESS(rv, rv);
3393 // Force the mimetype of the returned stream to be xml.
3394 rv = request->OverrideMimeType(NS_LITERAL_CSTRING("application/xml"));
3395 NS_ENSURE_SUCCESS(rv, rv);
3397 rv = request->Send(nsnull);
3398 NS_ENSURE_SUCCESS(rv, rv);
3400 nsCOMPtr<nsIDOMDocument> document;
3401 rv = request->GetResponseXML(getter_AddRefs(document));
3402 NS_ENSURE_SUCCESS(rv, rv);
3404 if (document) {
3405 document.swap(*aDocument);
3408 return NS_OK;