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