Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include "unoservices.hxx"
23 : #include "xml_import.hxx"
24 :
25 : #include <cppuhelper/factory.hxx>
26 : #include <cppuhelper/implementationentry.hxx>
27 : #include <cppuhelper/implbase1.hxx>
28 : #include <cppuhelper/implbase4.hxx>
29 : #include <cppuhelper/supportsservice.hxx>
30 : #include <com/sun/star/xml/input/XAttributes.hpp>
31 : #include <com/sun/star/lang/XInitialization.hpp>
32 : #include <com/sun/star/uno/XComponentContext.hpp>
33 : #include <com/sun/star/lang/XServiceInfo.hpp>
34 : #include <sal/log.hxx>
35 :
36 : #include <memory>
37 : #include <unordered_map>
38 : #include <vector>
39 :
40 : using namespace ::osl;
41 : using namespace ::com::sun::star;
42 : using namespace ::com::sun::star::uno;
43 :
44 : namespace xmlscript
45 : {
46 :
47 : const sal_Int32 UID_UNKNOWN = -1;
48 :
49 3 : Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl()
50 : {
51 3 : OUString name( "com.sun.star.xml.input.SaxDocumentHandler" );
52 3 : return Sequence< OUString >( &name, 1 );
53 : }
54 :
55 8 : OUString getImplementationName_DocumentHandlerImpl()
56 : {
57 8 : return OUString( "com.sun.star.comp.xml.input.SaxDocumentHandler" );
58 : }
59 :
60 : typedef std::unordered_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap;
61 :
62 2971 : struct PrefixEntry
63 : {
64 : ::std::vector< sal_Int32 > m_Uids;
65 :
66 2971 : inline PrefixEntry()
67 2971 : { m_Uids.reserve( 4 ); }
68 : };
69 :
70 : typedef std::unordered_map<
71 : OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap;
72 :
73 15362 : struct ElementEntry
74 : {
75 : Reference< xml::input::XElement > m_xElement;
76 : ::std::vector< OUString > m_prefixes;
77 :
78 15362 : inline ElementEntry()
79 15362 : { m_prefixes.reserve( 2 ); }
80 : };
81 :
82 : typedef ::std::vector< ElementEntry * > t_ElementVector;
83 :
84 : class ExtendedAttributes;
85 :
86 : struct MGuard
87 : {
88 : Mutex * m_pMutex;
89 87938 : explicit MGuard( Mutex * pMutex )
90 87938 : : m_pMutex( pMutex )
91 87938 : { if (m_pMutex) m_pMutex->acquire(); }
92 87938 : ~MGuard() throw ()
93 87938 : { if (m_pMutex) m_pMutex->release(); }
94 : };
95 :
96 : class DocumentHandlerImpl :
97 : public ::cppu::WeakImplHelper4< xml::sax::XDocumentHandler,
98 : xml::input::XNamespaceMapping,
99 : lang::XInitialization,
100 : com::sun::star::lang::XServiceInfo >
101 : {
102 : friend class ExtendedAttributes;
103 :
104 : Reference< xml::input::XRoot > m_xRoot;
105 :
106 : t_OUString2LongMap m_URI2Uid;
107 : sal_Int32 m_uid_count;
108 :
109 : OUString m_sXMLNS_PREFIX_UNKNOWN;
110 : OUString m_sXMLNS;
111 :
112 : sal_Int32 m_nLastURI_lookup;
113 : OUString m_aLastURI_lookup;
114 :
115 : t_OUString2PrefixMap m_prefixes;
116 : sal_Int32 m_nLastPrefix_lookup;
117 : OUString m_aLastPrefix_lookup;
118 :
119 : t_ElementVector m_elements;
120 : sal_Int32 m_nSkipElements;
121 :
122 : Mutex * m_pMutex;
123 :
124 : inline Reference< xml::input::XElement > getCurrentElement() const;
125 :
126 : inline sal_Int32 getUidByURI( OUString const & rURI );
127 : inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
128 :
129 : inline void pushPrefix(
130 : OUString const & rPrefix, OUString const & rURI );
131 : inline void popPrefix( OUString const & rPrefix );
132 :
133 : inline void getElementName(
134 : OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
135 :
136 : public:
137 : DocumentHandlerImpl(
138 : Reference< xml::input::XRoot > const & xRoot,
139 : bool bSingleThreadedUse );
140 : virtual ~DocumentHandlerImpl() throw ();
141 :
142 : // XServiceInfo
143 : virtual OUString SAL_CALL getImplementationName()
144 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
145 : virtual sal_Bool SAL_CALL supportsService(
146 : OUString const & servicename )
147 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
148 : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
149 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
150 :
151 : // XInitialization
152 : virtual void SAL_CALL initialize(
153 : Sequence< Any > const & arguments )
154 : throw (Exception, std::exception) SAL_OVERRIDE;
155 :
156 : // XDocumentHandler
157 : virtual void SAL_CALL startDocument()
158 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
159 : virtual void SAL_CALL endDocument()
160 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
161 : virtual void SAL_CALL startElement(
162 : OUString const & rQElementName,
163 : Reference< xml::sax::XAttributeList > const & xAttribs )
164 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
165 : virtual void SAL_CALL endElement(
166 : OUString const & rQElementName )
167 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
168 : virtual void SAL_CALL characters(
169 : OUString const & rChars )
170 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
171 : virtual void SAL_CALL ignorableWhitespace(
172 : OUString const & rWhitespaces )
173 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
174 : virtual void SAL_CALL processingInstruction(
175 : OUString const & rTarget, OUString const & rData )
176 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
177 : virtual void SAL_CALL setDocumentLocator(
178 : Reference< xml::sax::XLocator > const & xLocator )
179 : throw (xml::sax::SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
180 :
181 : // XNamespaceMapping
182 : virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri )
183 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
184 : virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid )
185 : throw (container::NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
186 : };
187 :
188 2573 : DocumentHandlerImpl::DocumentHandlerImpl(
189 : Reference< xml::input::XRoot > const & xRoot,
190 : bool bSingleThreadedUse )
191 : : m_xRoot( xRoot ),
192 : m_uid_count( 0 ),
193 : m_sXMLNS_PREFIX_UNKNOWN( "<<< unknown prefix >>>" ),
194 : m_sXMLNS( "xmlns" ),
195 : m_nLastURI_lookup( UID_UNKNOWN ),
196 : m_aLastURI_lookup( "<<< unknown URI >>>" ),
197 : m_nLastPrefix_lookup( UID_UNKNOWN ),
198 : m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
199 : m_nSkipElements( 0 ),
200 2573 : m_pMutex( 0 )
201 : {
202 2573 : m_elements.reserve( 10 );
203 :
204 2573 : if (! bSingleThreadedUse)
205 2 : m_pMutex = new Mutex();
206 2573 : }
207 :
208 7713 : DocumentHandlerImpl::~DocumentHandlerImpl() throw ()
209 : {
210 2571 : if (m_pMutex != 0)
211 : {
212 2 : delete m_pMutex;
213 : #if OSL_DEBUG_LEVEL == 0
214 2 : m_pMutex = 0;
215 : #endif
216 : }
217 5142 : }
218 :
219 : inline Reference< xml::input::XElement >
220 33664 : DocumentHandlerImpl::getCurrentElement() const
221 : {
222 33664 : MGuard aGuard( m_pMutex );
223 33664 : if (m_elements.empty())
224 0 : return Reference< xml::input::XElement >();
225 : else
226 33664 : return m_elements.back()->m_xElement;
227 : }
228 :
229 8187 : inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
230 : {
231 8187 : MGuard guard( m_pMutex );
232 8187 : if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
233 : {
234 8187 : t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
235 8187 : if (iFind != m_URI2Uid.end()) // id found
236 : {
237 2936 : m_nLastURI_lookup = iFind->second;
238 2936 : m_aLastURI_lookup = rURI;
239 : }
240 : else
241 : {
242 5251 : m_nLastURI_lookup = m_uid_count;
243 5251 : ++m_uid_count;
244 5251 : m_URI2Uid[ rURI ] = m_nLastURI_lookup;
245 5251 : m_aLastURI_lookup = rURI;
246 : }
247 : }
248 8187 : return m_nLastURI_lookup;
249 : }
250 :
251 42990 : inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
252 : OUString const & rPrefix )
253 : {
254 : // commonly the last added prefix is used often for several tags...
255 : // good guess
256 42990 : if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
257 : {
258 : t_OUString2PrefixMap::const_iterator iFind(
259 4360 : m_prefixes.find( rPrefix ) );
260 4360 : if (iFind != m_prefixes.end())
261 : {
262 4360 : const PrefixEntry & rPrefixEntry = *iFind->second;
263 : SAL_WARN_IF( rPrefixEntry.m_Uids.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
264 4360 : m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
265 4360 : m_aLastPrefix_lookup = rPrefix;
266 : }
267 : else
268 : {
269 0 : m_nLastPrefix_lookup = UID_UNKNOWN;
270 0 : m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
271 : }
272 : }
273 42990 : return m_nLastPrefix_lookup;
274 : }
275 :
276 2971 : inline void DocumentHandlerImpl::pushPrefix(
277 : OUString const & rPrefix, OUString const & rURI )
278 : {
279 : // lookup id for URI
280 2971 : sal_Int32 nUid = getUidByURI( rURI );
281 :
282 : // mark prefix with id
283 2971 : t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
284 2971 : if (iFind == m_prefixes.end()) // unused prefix
285 : {
286 2971 : PrefixEntry * pEntry = new PrefixEntry();
287 2971 : pEntry->m_Uids.push_back( nUid ); // latest id for prefix
288 2971 : m_prefixes[ rPrefix ] = pEntry;
289 : }
290 : else
291 : {
292 0 : PrefixEntry * pEntry = iFind->second;
293 : SAL_WARN_IF( pEntry->m_Uids.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty" );
294 0 : pEntry->m_Uids.push_back( nUid );
295 : }
296 :
297 2971 : m_aLastPrefix_lookup = rPrefix;
298 2971 : m_nLastPrefix_lookup = nUid;
299 2971 : }
300 :
301 2971 : inline void DocumentHandlerImpl::popPrefix(
302 : OUString const & rPrefix )
303 : {
304 2971 : t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
305 2971 : if (iFind != m_prefixes.end()) // unused prefix
306 : {
307 2971 : PrefixEntry * pEntry = iFind->second;
308 2971 : pEntry->m_Uids.pop_back(); // pop last id for prefix
309 2971 : if (pEntry->m_Uids.empty()) // erase prefix key
310 : {
311 2971 : m_prefixes.erase( iFind );
312 2971 : delete pEntry;
313 : }
314 : }
315 :
316 2971 : m_nLastPrefix_lookup = UID_UNKNOWN;
317 2971 : m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
318 2971 : }
319 :
320 15362 : inline void DocumentHandlerImpl::getElementName(
321 : OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
322 : {
323 15362 : sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' );
324 15362 : *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
325 : *pUid = getUidByPrefix(
326 15362 : nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
327 15362 : }
328 :
329 : class ExtendedAttributes :
330 : public ::cppu::WeakImplHelper1< xml::input::XAttributes >
331 : {
332 : sal_Int32 m_nAttributes;
333 : sal_Int32 * m_pUids;
334 : OUString * m_pPrefixes;
335 : OUString * m_pLocalNames;
336 : OUString * m_pQNames;
337 : OUString * m_pValues;
338 :
339 : DocumentHandlerImpl * m_pHandler;
340 :
341 : public:
342 : inline ExtendedAttributes(
343 : sal_Int32 nAttributes,
344 : sal_Int32 * pUids, OUString * pPrefixes,
345 : OUString * pLocalNames, OUString * pQNames,
346 : Reference< xml::sax::XAttributeList > const & xAttributeList,
347 : DocumentHandlerImpl * pHandler );
348 : virtual ~ExtendedAttributes() throw ();
349 :
350 : // XAttributes
351 : virtual sal_Int32 SAL_CALL getLength()
352 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
353 : virtual sal_Int32 SAL_CALL getIndexByQName(
354 : OUString const & rQName )
355 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
356 : virtual sal_Int32 SAL_CALL getIndexByUidName(
357 : sal_Int32 nUid, OUString const & rLocalName )
358 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
359 : virtual OUString SAL_CALL getQNameByIndex(
360 : sal_Int32 nIndex )
361 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
362 : virtual sal_Int32 SAL_CALL getUidByIndex(
363 : sal_Int32 nIndex )
364 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
365 : virtual OUString SAL_CALL getLocalNameByIndex(
366 : sal_Int32 nIndex )
367 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
368 : virtual OUString SAL_CALL getValueByIndex(
369 : sal_Int32 nIndex )
370 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
371 : virtual OUString SAL_CALL getValueByUidName(
372 : sal_Int32 nUid, OUString const & rLocalName )
373 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
374 : virtual OUString SAL_CALL getTypeByIndex(
375 : sal_Int32 nIndex )
376 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
377 : };
378 :
379 15362 : inline ExtendedAttributes::ExtendedAttributes(
380 : sal_Int32 nAttributes,
381 : sal_Int32 * pUids, OUString * pPrefixes,
382 : OUString * pLocalNames, OUString * pQNames,
383 : Reference< xml::sax::XAttributeList > const & xAttributeList,
384 : DocumentHandlerImpl * pHandler )
385 : : m_nAttributes( nAttributes )
386 : , m_pUids( pUids )
387 : , m_pPrefixes( pPrefixes )
388 : , m_pLocalNames( pLocalNames )
389 : , m_pQNames( pQNames )
390 30724 : , m_pValues( new OUString[ nAttributes ] )
391 46086 : , m_pHandler( pHandler )
392 : {
393 15362 : m_pHandler->acquire();
394 :
395 45961 : for ( sal_Int32 nPos = 0; nPos < nAttributes; ++nPos )
396 : {
397 30599 : m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
398 : }
399 15362 : }
400 :
401 46041 : ExtendedAttributes::~ExtendedAttributes() throw ()
402 : {
403 15347 : m_pHandler->release();
404 :
405 15347 : delete [] m_pUids;
406 15347 : delete [] m_pPrefixes;
407 15347 : delete [] m_pLocalNames;
408 15347 : delete [] m_pQNames;
409 15347 : delete [] m_pValues;
410 30694 : }
411 :
412 : // XServiceInfo
413 :
414 1 : OUString DocumentHandlerImpl::getImplementationName()
415 : throw (RuntimeException, std::exception)
416 : {
417 1 : return getImplementationName_DocumentHandlerImpl();
418 : }
419 :
420 0 : sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
421 : throw (RuntimeException, std::exception)
422 : {
423 0 : return cppu::supportsService(this, servicename);
424 : }
425 :
426 1 : Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
427 : throw (RuntimeException, std::exception)
428 : {
429 1 : return getSupportedServiceNames_DocumentHandlerImpl();
430 : }
431 :
432 : // XInitialization
433 :
434 1 : void DocumentHandlerImpl::initialize(
435 : Sequence< Any > const & arguments )
436 : throw (Exception, std::exception)
437 : {
438 1 : MGuard guard( m_pMutex );
439 2 : Reference< xml::input::XRoot > xRoot;
440 3 : if (arguments.getLength() == 1 &&
441 2 : (arguments[ 0 ] >>= xRoot) &&
442 1 : xRoot.is())
443 : {
444 1 : m_xRoot = xRoot;
445 : }
446 : else
447 : {
448 0 : throw RuntimeException( "missing root instance!" );
449 1 : }
450 1 : }
451 :
452 : // XNamespaceMapping
453 :
454 5216 : sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
455 : throw (RuntimeException, std::exception)
456 : {
457 5216 : sal_Int32 uid = getUidByURI( Uri );
458 : SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
459 5216 : return uid;
460 : }
461 :
462 0 : OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
463 : throw (container::NoSuchElementException, RuntimeException, std::exception)
464 : {
465 0 : MGuard guard( m_pMutex );
466 0 : t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() );
467 0 : t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() );
468 0 : for ( ; iPos != iEnd; ++iPos )
469 : {
470 0 : if (iPos->second == Uid)
471 0 : return iPos->first;
472 : }
473 0 : throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject * >(this) );
474 : }
475 :
476 : // XDocumentHandler
477 :
478 2572 : void DocumentHandlerImpl::startDocument()
479 : throw (xml::sax::SAXException, RuntimeException, std::exception)
480 : {
481 2572 : m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
482 2572 : }
483 :
484 2572 : void DocumentHandlerImpl::endDocument()
485 : throw (xml::sax::SAXException, RuntimeException, std::exception)
486 : {
487 2572 : m_xRoot->endDocument();
488 2572 : }
489 :
490 15362 : void DocumentHandlerImpl::startElement(
491 : OUString const & rQElementName,
492 : Reference< xml::sax::XAttributeList > const & xAttribs )
493 : throw (xml::sax::SAXException, RuntimeException, std::exception)
494 : {
495 15362 : Reference< xml::input::XElement > xCurrentElement;
496 30724 : Reference< xml::input::XAttributes > xAttributes;
497 : sal_Int32 nUid;
498 30724 : OUString aLocalName;
499 30724 : ::std::unique_ptr< ElementEntry > elementEntry( new ElementEntry );
500 :
501 : { // guard start:
502 15362 : MGuard aGuard( m_pMutex );
503 : // currently skipping elements and waiting for end tags?
504 15362 : if (m_nSkipElements > 0)
505 : {
506 0 : ++m_nSkipElements; // wait for another end tag
507 : #if OSL_DEBUG_LEVEL > 1
508 : OString aQName(
509 : OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
510 : SAL_INFO("xmlscript.xmlhelper", "### no context given on createChildElement() => ignoring element \"" << aQName.getStr() << "\" ...");
511 : #endif
512 15362 : return;
513 : }
514 :
515 15362 : sal_Int16 nAttribs = xAttribs->getLength();
516 :
517 : // save all namespace ids
518 15362 : sal_Int32 * pUids = new sal_Int32[ nAttribs ];
519 15362 : OUString * pPrefixes = new OUString[ nAttribs ];
520 15362 : OUString * pLocalNames = new OUString[ nAttribs ];
521 15362 : OUString * pQNames = new OUString[ nAttribs ];
522 :
523 : // first recognize all xmlns attributes
524 : sal_Int16 nPos;
525 45961 : for ( nPos = 0; nPos < nAttribs; ++nPos )
526 : {
527 : // mark attribute to be collected further
528 : // on with attribute's uid and current prefix
529 30599 : pUids[ nPos ] = 0; // modified
530 :
531 30599 : pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
532 30599 : OUString const & rQAttributeName = pQNames[ nPos ];
533 :
534 30599 : if (rQAttributeName.startsWith( m_sXMLNS ))
535 : {
536 2971 : if (rQAttributeName.getLength() == 5) // set default namespace
537 : {
538 0 : OUString aDefNamespacePrefix;
539 : pushPrefix(
540 : aDefNamespacePrefix,
541 0 : xAttribs->getValueByIndex( nPos ) );
542 0 : elementEntry->m_prefixes.push_back( aDefNamespacePrefix );
543 0 : pUids[ nPos ] = UID_UNKNOWN;
544 0 : pPrefixes[ nPos ] = m_sXMLNS;
545 0 : pLocalNames[ nPos ] = aDefNamespacePrefix;
546 : }
547 2971 : else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix
548 : {
549 2971 : OUString aPrefix( rQAttributeName.copy( 6 ) );
550 2971 : pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
551 2971 : elementEntry->m_prefixes.push_back( aPrefix );
552 2971 : pUids[ nPos ] = UID_UNKNOWN;
553 2971 : pPrefixes[ nPos ] = m_sXMLNS;
554 2971 : pLocalNames[ nPos ] = aPrefix;
555 : }
556 : // else just a name starting with xmlns, but no prefix
557 : }
558 : }
559 :
560 : // now read out attribute prefixes (all namespace prefixes have been set)
561 45961 : for ( nPos = 0; nPos < nAttribs; ++nPos )
562 : {
563 30599 : if (pUids[ nPos ] >= 0) // no xmlns: attribute
564 : {
565 27628 : OUString const & rQAttributeName = pQNames[ nPos ];
566 : SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
567 :
568 : // collect attribute's uid and current prefix
569 27628 : sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' );
570 27628 : if (nColonPos >= 0)
571 : {
572 27628 : pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
573 27628 : pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
574 : }
575 : else
576 : {
577 0 : pPrefixes[ nPos ].clear();
578 0 : pLocalNames[ nPos ] = rQAttributeName;
579 : // leave local names unmodified
580 : }
581 27628 : pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
582 : }
583 : }
584 : // ownership of arrays belongs to attribute list
585 : xAttributes = static_cast< xml::input::XAttributes * >(
586 : new ExtendedAttributes(
587 : nAttribs, pUids, pPrefixes, pLocalNames, pQNames,
588 15362 : xAttribs, this ) );
589 :
590 15362 : getElementName( rQElementName, &nUid, &aLocalName );
591 :
592 : // create new child context and append to list
593 15362 : if (! m_elements.empty())
594 12790 : xCurrentElement = m_elements.back()->m_xElement;
595 : } // :guard end
596 :
597 15362 : if (xCurrentElement.is())
598 : {
599 25580 : elementEntry->m_xElement =
600 25580 : xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
601 : }
602 : else
603 : {
604 5144 : elementEntry->m_xElement =
605 5144 : m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
606 : }
607 :
608 : {
609 15362 : MGuard aGuard( m_pMutex );
610 15362 : if (elementEntry->m_xElement.is())
611 : {
612 15362 : m_elements.push_back( elementEntry.release() );
613 : }
614 : else
615 : {
616 0 : ++m_nSkipElements;
617 : #if OSL_DEBUG_LEVEL > 1
618 : OString aQName(
619 : OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
620 : SAL_INFO("xmlscript.xmlhelper", "### no context given on createChildElement() => ignoring element \"" << aQName.getStr() << "\" ...");
621 : #endif
622 15362 : }
623 15362 : }
624 : }
625 :
626 15362 : void DocumentHandlerImpl::endElement(
627 : OUString const & rQElementName )
628 : throw (xml::sax::SAXException, RuntimeException, std::exception)
629 : {
630 15362 : Reference< xml::input::XElement > xCurrentElement;
631 : {
632 15362 : MGuard aGuard( m_pMutex );
633 15362 : if (m_nSkipElements)
634 : {
635 0 : --m_nSkipElements;
636 : #if OSL_DEBUG_LEVEL > 1
637 : OString aQName(
638 : OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
639 : SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << aQName.getStr() << "\".");
640 : #endif
641 : static_cast<void>(rQElementName);
642 15362 : return;
643 : }
644 :
645 : // popping context
646 : SAL_WARN_IF( m_elements.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
647 15362 : ElementEntry * pEntry = m_elements.back();
648 15362 : xCurrentElement = pEntry->m_xElement;
649 :
650 : #if OSL_DEBUG_LEVEL > 0
651 : sal_Int32 nUid;
652 : OUString aLocalName;
653 : getElementName( rQElementName, &nUid, &aLocalName );
654 : SAL_WARN_IF( xCurrentElement->getLocalName() != aLocalName, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
655 : SAL_WARN_IF( xCurrentElement->getUid() != nUid, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
656 : #endif
657 :
658 : // pop prefixes
659 33695 : for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; )
660 : {
661 2971 : popPrefix( pEntry->m_prefixes[ nPos ] );
662 : }
663 15362 : m_elements.pop_back();
664 15362 : delete pEntry;
665 : }
666 15362 : xCurrentElement->endElement();
667 : }
668 :
669 33664 : void DocumentHandlerImpl::characters( OUString const & rChars )
670 : throw (xml::sax::SAXException, RuntimeException, std::exception)
671 : {
672 33664 : Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
673 33664 : if (xCurrentElement.is())
674 33664 : xCurrentElement->characters( rChars );
675 33664 : }
676 :
677 0 : void DocumentHandlerImpl::ignorableWhitespace(
678 : OUString const & rWhitespaces )
679 : throw (xml::sax::SAXException, RuntimeException, std::exception)
680 : {
681 0 : Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
682 0 : if (xCurrentElement.is())
683 0 : xCurrentElement->ignorableWhitespace( rWhitespaces );
684 0 : }
685 :
686 0 : void DocumentHandlerImpl::processingInstruction(
687 : OUString const & rTarget, OUString const & rData )
688 : throw (xml::sax::SAXException, RuntimeException, std::exception)
689 : {
690 0 : Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
691 0 : if (xCurrentElement.is())
692 0 : xCurrentElement->processingInstruction( rTarget, rData );
693 : else
694 0 : m_xRoot->processingInstruction( rTarget, rData );
695 0 : }
696 :
697 2571 : void DocumentHandlerImpl::setDocumentLocator(
698 : Reference< xml::sax::XLocator > const & xLocator )
699 : throw (xml::sax::SAXException, RuntimeException, std::exception)
700 : {
701 2571 : m_xRoot->setDocumentLocator( xLocator );
702 2571 : }
703 :
704 : // XAttributes
705 :
706 0 : sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
707 : throw (RuntimeException, std::exception)
708 : {
709 0 : for ( sal_Int32 nPos = m_nAttributes; nPos--; )
710 : {
711 0 : if (m_pQNames[ nPos ].equals( rQName ))
712 : {
713 0 : return nPos;
714 : }
715 : }
716 0 : return -1;
717 : }
718 :
719 0 : sal_Int32 ExtendedAttributes::getLength()
720 : throw (RuntimeException, std::exception)
721 : {
722 0 : return m_nAttributes;
723 : }
724 :
725 0 : OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
726 : throw (RuntimeException, std::exception)
727 : {
728 0 : if (nIndex < m_nAttributes)
729 0 : return m_pLocalNames[ nIndex ];
730 : else
731 0 : return OUString();
732 : }
733 :
734 0 : OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
735 : throw (RuntimeException, std::exception)
736 : {
737 0 : if (nIndex < m_nAttributes)
738 0 : return m_pQNames[ nIndex ];
739 : else
740 0 : return OUString();
741 : }
742 :
743 0 : OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
744 : throw (RuntimeException, std::exception)
745 : {
746 : static_cast<void>(nIndex);
747 : SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
748 0 : return OUString(); // unsupported
749 : }
750 :
751 0 : OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
752 : throw (RuntimeException, std::exception)
753 : {
754 0 : if (nIndex < m_nAttributes)
755 0 : return m_pValues[ nIndex ];
756 : else
757 0 : return OUString();
758 : }
759 :
760 0 : sal_Int32 ExtendedAttributes::getIndexByUidName(
761 : sal_Int32 nUid, OUString const & rLocalName )
762 : throw (RuntimeException, std::exception)
763 : {
764 0 : for ( sal_Int32 nPos = m_nAttributes; nPos--; )
765 : {
766 0 : if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
767 : {
768 0 : return nPos;
769 : }
770 : }
771 0 : return -1;
772 : }
773 :
774 0 : sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
775 : throw (RuntimeException, std::exception)
776 : {
777 0 : if (nIndex < m_nAttributes)
778 0 : return m_pUids[ nIndex ];
779 : else
780 0 : return -1;
781 : }
782 :
783 30668 : OUString ExtendedAttributes::getValueByUidName(
784 : sal_Int32 nUid, OUString const & rLocalName )
785 : throw (RuntimeException, std::exception)
786 : {
787 107372 : for ( sal_Int32 nPos = m_nAttributes; nPos--; )
788 : {
789 71666 : if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
790 : {
791 25630 : return m_pValues[ nPos ];
792 : }
793 : }
794 5038 : return OUString();
795 : }
796 :
797 2571 : Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler(
798 : Reference< xml::input::XRoot > const & xRoot,
799 : bool bSingleThreadedUse )
800 : {
801 : SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
802 2571 : if (xRoot.is())
803 : {
804 : return static_cast< xml::sax::XDocumentHandler * >(
805 2571 : new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) );
806 : }
807 0 : return Reference< xml::sax::XDocumentHandler >();
808 : }
809 :
810 2 : Reference< XInterface > SAL_CALL create_DocumentHandlerImpl(
811 : SAL_UNUSED_PARAMETER Reference< XComponentContext > const & )
812 : {
813 : return static_cast< ::cppu::OWeakObject * >(
814 : new DocumentHandlerImpl(
815 2 : Reference< xml::input::XRoot >(), false /* mt use */ ) );
816 : }
817 :
818 : }
819 :
820 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|