1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
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/
9 : *
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.
14 : *
15 : * The Original Code is TransforMiiX XSLT processor code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2001
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Peter Van der Beken <peterv@propagandism.org>
24 : *
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.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsXPathExpression.h"
40 : #include "txExpr.h"
41 : #include "txExprResult.h"
42 : #include "nsDOMError.h"
43 : #include "nsIDOMCharacterData.h"
44 : #include "nsDOMClassInfoID.h"
45 : #include "nsIDOMDocument.h"
46 : #include "nsIDOMXPathNamespace.h"
47 : #include "nsXPathResult.h"
48 : #include "nsDOMError.h"
49 : #include "txURIUtils.h"
50 : #include "txXPathTreeWalker.h"
51 :
52 1516 : NS_IMPL_CYCLE_COLLECTION_1(nsXPathExpression, mDocument)
53 :
54 236 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPathExpression)
55 278 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPathExpression)
56 :
57 : DOMCI_DATA(XPathExpression, nsXPathExpression)
58 :
59 686 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXPathExpression)
60 378 : NS_INTERFACE_MAP_ENTRY(nsIDOMXPathExpression)
61 252 : NS_INTERFACE_MAP_ENTRY(nsIDOMNSXPathExpression)
62 252 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathExpression)
63 210 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XPathExpression)
64 168 : NS_INTERFACE_MAP_END
65 :
66 42 : nsXPathExpression::nsXPathExpression(nsAutoPtr<Expr>& aExpression,
67 : txResultRecycler* aRecycler,
68 : nsIDOMDocument *aDocument)
69 : : mExpression(aExpression),
70 : mRecycler(aRecycler),
71 42 : mDocument(aDocument)
72 : {
73 42 : }
74 :
75 : NS_IMETHODIMP
76 42 : nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
77 : PRUint16 aType,
78 : nsISupports *aInResult,
79 : nsISupports **aResult)
80 : {
81 42 : return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aResult);
82 : }
83 :
84 : NS_IMETHODIMP
85 42 : nsXPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode,
86 : PRUint32 aContextPosition,
87 : PRUint32 aContextSize,
88 : PRUint16 aType,
89 : nsISupports *aInResult,
90 : nsISupports **aResult)
91 : {
92 84 : nsCOMPtr<nsINode> context = do_QueryInterface(aContextNode);
93 42 : NS_ENSURE_ARG(context);
94 :
95 42 : if (aContextPosition > aContextSize)
96 0 : return NS_ERROR_FAILURE;
97 :
98 42 : if (!nsContentUtils::CanCallerAccess(aContextNode))
99 0 : return NS_ERROR_DOM_SECURITY_ERR;
100 :
101 42 : if (mDocument && mDocument != aContextNode) {
102 84 : nsCOMPtr<nsIDOMDocument> contextDocument;
103 42 : aContextNode->GetOwnerDocument(getter_AddRefs(contextDocument));
104 :
105 42 : if (mDocument != contextDocument) {
106 0 : return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
107 : }
108 : }
109 :
110 42 : PRUint16 nodeType = context->NodeType();
111 :
112 42 : if (nodeType == nsIDOMNode::TEXT_NODE ||
113 : nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
114 66 : nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aContextNode);
115 33 : NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE);
116 :
117 33 : if (textNode) {
118 : PRUint32 textLength;
119 33 : textNode->GetLength(&textLength);
120 33 : if (textLength == 0)
121 0 : return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
122 33 : }
123 :
124 : // XXX Need to get logical XPath text node for CDATASection
125 : // and Text nodes.
126 : }
127 9 : else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
128 : nodeType != nsIDOMNode::ELEMENT_NODE &&
129 : nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
130 : nodeType != nsIDOMNode::COMMENT_NODE &&
131 : nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE &&
132 : nodeType != nsIDOMXPathNamespace::XPATH_NAMESPACE_NODE) {
133 0 : return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
134 : }
135 :
136 42 : NS_ENSURE_ARG(aResult);
137 42 : *aResult = nsnull;
138 :
139 84 : nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(aContextNode));
140 42 : if (!contextNode) {
141 0 : return NS_ERROR_OUT_OF_MEMORY;
142 : }
143 :
144 42 : EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
145 126 : mRecycler);
146 84 : nsRefPtr<txAExprResult> exprResult;
147 42 : nsresult rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
148 42 : NS_ENSURE_SUCCESS(rv, rv);
149 :
150 42 : PRUint16 resultType = aType;
151 42 : if (aType == nsIDOMXPathResult::ANY_TYPE) {
152 0 : short exprResultType = exprResult->getResultType();
153 0 : switch (exprResultType) {
154 : case txAExprResult::NUMBER:
155 0 : resultType = nsIDOMXPathResult::NUMBER_TYPE;
156 0 : break;
157 : case txAExprResult::STRING:
158 0 : resultType = nsIDOMXPathResult::STRING_TYPE;
159 0 : break;
160 : case txAExprResult::BOOLEAN:
161 0 : resultType = nsIDOMXPathResult::BOOLEAN_TYPE;
162 0 : break;
163 : case txAExprResult::NODESET:
164 0 : resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE;
165 0 : break;
166 : case txAExprResult::RESULT_TREE_FRAGMENT:
167 0 : NS_ERROR("Can't return a tree fragment!");
168 0 : return NS_ERROR_FAILURE;
169 : }
170 : }
171 :
172 : // We need a result object and it must be our implementation.
173 84 : nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult);
174 42 : if (!xpathResult) {
175 : // Either no aInResult or not one of ours.
176 42 : xpathResult = new nsXPathResult();
177 42 : NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY);
178 : }
179 42 : rv = xpathResult->SetExprResult(exprResult, resultType, context);
180 42 : NS_ENSURE_SUCCESS(rv, rv);
181 :
182 42 : return CallQueryInterface(xpathResult, aResult);
183 : }
184 :
185 : /*
186 : * Implementation of the txIEvalContext private to nsXPathExpression
187 : * EvalContextImpl bases on only one context node and no variables
188 : */
189 :
190 : nsresult
191 0 : nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace,
192 : nsIAtom* aLName,
193 : txAExprResult*& aResult)
194 : {
195 0 : aResult = 0;
196 0 : return NS_ERROR_INVALID_ARG;
197 : }
198 :
199 33 : bool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode)
200 : {
201 33 : return false;
202 : }
203 :
204 0 : void* nsXPathExpression::EvalContextImpl::getPrivateContext()
205 : {
206 : // we don't have a private context here.
207 0 : return nsnull;
208 : }
209 :
210 42 : txResultRecycler* nsXPathExpression::EvalContextImpl::recycler()
211 : {
212 42 : return mRecycler;
213 : }
214 :
215 0 : void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg,
216 : nsresult aRes)
217 : {
218 0 : mLastError = aRes;
219 : // forward aMsg to console service?
220 0 : }
221 :
222 42 : const txXPathNode& nsXPathExpression::EvalContextImpl::getContextNode()
223 : {
224 42 : return mContextNode;
225 : }
226 :
227 0 : PRUint32 nsXPathExpression::EvalContextImpl::size()
228 : {
229 0 : return mContextSize;
230 : }
231 :
232 0 : PRUint32 nsXPathExpression::EvalContextImpl::position()
233 : {
234 0 : return mContextPosition;
235 4392 : }
|