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