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 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 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 88 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; 100 explicit MGuard( Mutex * pMutex ) 101 : m_pMutex( pMutex ) 102 { if (m_pMutex) m_pMutex->acquire(); } 103 ~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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 > 236 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 443 OUString DocumentHandlerImpl::getImplementationName() 444 throw (RuntimeException) 445 { 446 return getImplementationName_DocumentHandlerImpl(); 447 } 448 449 //______________________________________________________________________________ 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 //______________________________________________________________________________ 464 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames() 465 throw (RuntimeException) 466 { 467 return getSupportedServiceNames_DocumentHandlerImpl(); 468 } 469 470 // XInitialization 471 472 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 535 void DocumentHandlerImpl::endDocument() 536 throw (xml::sax::SAXException, RuntimeException) 537 { 538 m_xRoot->endDocument(); 539 } 540 541 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 786 sal_Int32 ExtendedAttributes::getLength() 787 throw (RuntimeException) 788 { 789 return m_nAttributes; 790 } 791 792 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //______________________________________________________________________________ 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 //============================================================================== 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 //------------------------------------------------------------------------------ 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