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