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