source: trunk/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp@ 1023

Last change on this file since 1023 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 15.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtCore/QFile>
43#include <QtCore/QTextCodec>
44#include <QtCore/QTimer>
45#include <QtCore/QXmlStreamReader>
46
47#include <QtNetwork/QNetworkRequest>
48
49#include "qatomicstring_p.h"
50#include "qautoptr_p.h"
51#include "qcommonsequencetypes_p.h"
52
53#include "qacceltreeresourceloader_p.h"
54
55QT_BEGIN_NAMESPACE
56
57using namespace QPatternist;
58
59AccelTreeResourceLoader::AccelTreeResourceLoader(const NamePool::Ptr &np,
60 const NetworkAccessDelegator::Ptr &manager,
61 AccelTreeBuilder<true>::Features features)
62 : m_namePool(np)
63 , m_networkAccessDelegator(manager)
64 , m_features(features)
65{
66 Q_ASSERT(m_namePool);
67 Q_ASSERT(m_networkAccessDelegator);
68}
69
70bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri,
71 const ReportContext::Ptr &context)
72{
73 Q_ASSERT(uri.isValid());
74 AccelTreeBuilder<true> builder(uri, uri, m_namePool, context.data(), m_features);
75
76 const AutoPtr<QNetworkReply> reply(load(uri, m_networkAccessDelegator, context));
77
78 if(!reply)
79 return false;
80
81 bool success = false;
82 success = streamToReceiver(reply.data(), &builder, m_namePool, context, uri);
83
84 m_loadedDocuments.insert(uri, builder.builtDocument());
85 return success;
86}
87
88bool AccelTreeResourceLoader::retrieveDocument(QIODevice *source, const QUrl &documentUri, const ReportContext::Ptr &context)
89{
90 Q_ASSERT(source);
91 Q_ASSERT(source->isReadable());
92 Q_ASSERT(documentUri.isValid());
93
94 AccelTreeBuilder<true> builder(documentUri, documentUri, m_namePool, context.data(), m_features);
95
96 bool success = false;
97 success = streamToReceiver(source, &builder, m_namePool, context, documentUri);
98
99 m_loadedDocuments.insert(documentUri, builder.builtDocument());
100
101 return success;
102}
103
104QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
105 const NetworkAccessDelegator::Ptr &networkDelegator,
106 const ReportContext::Ptr &context, ErrorHandling errorHandling)
107{
108 return load(uri,
109 networkDelegator->managerFor(uri),
110 context, errorHandling);
111}
112
113QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
114 QNetworkAccessManager *const networkManager,
115 const ReportContext::Ptr &context, ErrorHandling errorHandling)
116
117{
118 Q_ASSERT(networkManager);
119 Q_ASSERT(uri.isValid());
120
121 NetworkLoop networkLoop;
122
123 QNetworkRequest request(uri);
124 QNetworkReply *const reply = networkManager->get(request);
125 networkLoop.connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
126 networkLoop.connect(reply, SIGNAL(finished()), SLOT(finished()));
127
128 if(networkLoop.exec(QEventLoop::ExcludeUserInputEvents))
129 {
130 const QString errorMessage(escape(reply->errorString()));
131
132 /* Note, we delete reply before we exit this function with error(). */
133 delete reply;
134
135 const QSourceLocation location(uri);
136
137 if(context && (errorHandling == FailOnError))
138 context->error(errorMessage, ReportContext::FODC0002, location);
139
140 return 0;
141 }
142 else
143 return reply;
144}
145
146bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev,
147 AccelTreeBuilder<true> *const receiver,
148 const NamePool::Ptr &np,
149 const ReportContext::Ptr &context,
150 const QUrl &uri)
151{
152 Q_ASSERT(dev);
153 Q_ASSERT(receiver);
154 Q_ASSERT(np);
155
156 QXmlStreamReader reader(dev);
157
158 /* Optimize: change NamePool to take QStringRef such that we don't have to call toString() below. That
159 * will save us a gazillion of temporary QStrings. */
160
161 while(!reader.atEnd())
162 {
163 reader.readNext();
164
165 switch(reader.tokenType())
166 {
167 case QXmlStreamReader::StartElement:
168 {
169 /* Send the name. */
170 receiver->startElement(np->allocateQName(reader.namespaceUri().toString(), reader.name().toString(),
171 reader.prefix().toString()), reader.lineNumber(), reader.columnNumber());
172
173 /* Send namespace declarations. */
174 const QXmlStreamNamespaceDeclarations &nss = reader.namespaceDeclarations();
175
176 /* The far most common case, is for it to be empty. */
177 if(!nss.isEmpty())
178 {
179 const int len = nss.size();
180
181 for(int i = 0; i < len; ++i)
182 {
183 const QXmlStreamNamespaceDeclaration &ns = nss.at(i);
184 receiver->namespaceBinding(np->allocateBinding(ns.prefix().toString(), ns.namespaceUri().toString()));
185 }
186 }
187
188 /* Send attributes. */
189 const QXmlStreamAttributes &attrs = reader.attributes();
190 const int len = attrs.size();
191
192 for(int i = 0; i < len; ++i)
193 {
194 const QXmlStreamAttribute &attr = attrs.at(i);
195
196 receiver->attribute(np->allocateQName(attr.namespaceUri().toString(), attr.name().toString(),
197 attr.prefix().toString()),
198 attr.value());
199 }
200
201 continue;
202 }
203 case QXmlStreamReader::EndElement:
204 {
205 receiver->endElement();
206 continue;
207 }
208 case QXmlStreamReader::Characters:
209 {
210 if(reader.isWhitespace())
211 receiver->whitespaceOnly(reader.text());
212 else
213 receiver->characters(reader.text());
214
215 continue;
216 }
217 case QXmlStreamReader::Comment:
218 {
219 receiver->comment(reader.text().toString());
220 continue;
221 }
222 case QXmlStreamReader::ProcessingInstruction:
223 {
224 receiver->processingInstruction(np->allocateQName(QString(), reader.processingInstructionTarget().toString()),
225 reader.processingInstructionData().toString());
226 continue;
227 }
228 case QXmlStreamReader::StartDocument:
229 {
230 receiver->startDocument();
231 continue;
232 }
233 case QXmlStreamReader::EndDocument:
234 {