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