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_xmlsecurity.hxx" 26 27 #include "saxeventkeeperimpl.hxx" 28 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 29 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 30 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp> 31 32 namespace cssu = com::sun::star::uno; 33 namespace cssl = com::sun::star::lang; 34 namespace cssxc = com::sun::star::xml::crypto; 35 namespace cssxcsax = com::sun::star::xml::csax; 36 namespace cssxw = com::sun::star::xml::wrapper; 37 namespace cssxs = com::sun::star::xml::sax; 38 39 #define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper" 40 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl" 41 42 #define _USECOMPRESSEDDOCUMENTHANDLER 43 44 SAXEventKeeperImpl::SAXEventKeeperImpl( ) 45 :m_pRootBufferNode(NULL), 46 m_pCurrentBufferNode(NULL), 47 m_nNextElementMarkId(1), 48 m_pNewBlocker(NULL), 49 m_pCurrentBlockingBufferNode(NULL), 50 m_bIsReleasing(false), 51 m_bIsForwarding(false) 52 { 53 m_vElementMarkBuffers.reserve(2); 54 m_vNewElementCollectors.reserve(2); 55 m_vReleasedElementMarkBuffers.reserve(2); 56 } 57 58 SAXEventKeeperImpl::~SAXEventKeeperImpl() 59 { 60 /* 61 * delete the BufferNode tree 62 */ 63 if (m_pRootBufferNode != NULL) 64 { 65 m_pRootBufferNode->freeAllChildren(); 66 delete m_pRootBufferNode; 67 } 68 69 m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL; 70 71 /* 72 * delete all unfreed ElementMarks 73 */ 74 m_vNewElementCollectors.clear(); 75 m_pNewBlocker = NULL; 76 77 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin(); 78 for( ; ii != m_vElementMarkBuffers.end(); ++ii ) 79 { 80 delete (*ii); 81 } 82 m_vElementMarkBuffers.clear(); 83 } 84 85 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode) 86 /****** SAXEventKeeperImpl/setCurrentBufferNode ****************************** 87 * 88 * NAME 89 * setCurrentBufferNode -- set a new active BufferNode. 90 * 91 * SYNOPSIS 92 * setCurrentBufferNode( pBufferNode ); 93 * 94 * FUNCTION 95 * connects this BufferNode into the BufferNode tree as a child of the 96 * current active BufferNode. Then makes this BufferNode as the current 97 * active BufferNode. 98 * If the previous active BufferNode points to the root 99 * BufferNode, which means that no buffering operation was proceeding, 100 * then notifies the status change listener that buffering operation 101 * will begin at once. 102 * 103 * INPUTS 104 * pBufferNode - a BufferNode which will be the new active BufferNode 105 * 106 * RESULT 107 * empty 108 * 109 * HISTORY 110 * 05.01.2004 - implemented 111 * 112 * AUTHOR 113 * Michael Mi 114 * Email: michael.mi@sun.com 115 ******************************************************************************/ 116 { 117 if (pBufferNode != m_pCurrentBufferNode) 118 { 119 if ( m_pCurrentBufferNode == m_pRootBufferNode && 120 m_xSAXEventKeeperStatusChangeListener.is()) 121 { 122 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True); 123 } 124 125 if (pBufferNode->getParent() == NULL) 126 { 127 m_pCurrentBufferNode->addChild(pBufferNode); 128 pBufferNode->setParent(m_pCurrentBufferNode); 129 } 130 131 m_pCurrentBufferNode = pBufferNode; 132 } 133 } 134 135 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers() 136 /****** SAXEventKeeperImpl/addNewElementMarkBuffers ************************** 137 * 138 * NAME 139 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker. 140 * 141 * SYNOPSIS 142 * pBufferNode = addNewElementMarkBuffers( ); 143 * 144 * FUNCTION 145 * if there are new ElementCollector or new Blocker to be added, then 146 * connect all of them with the current BufferNode. In case of the 147 * current BufferNode doesn't exist, creates one. 148 * Clears up the new ElementCollector list and the new Blocker pointer. 149 * 150 * INPUTS 151 * empty 152 * 153 * RESULT 154 * pBufferNode - the BufferNode that has been connected with both new 155 * ElementCollectors and new Blocker. 156 * 157 * HISTORY 158 * 05.01.2004 - implemented 159 * 160 * AUTHOR 161 * Michael Mi 162 * Email: michael.mi@sun.com 163 ******************************************************************************/ 164 { 165 BufferNode* pBufferNode = NULL; 166 167 if ( (m_vNewElementCollectors.size()>0) || 168 (m_pNewBlocker != NULL)) 169 { 170 /* 171 * When the current BufferNode is right pointing to the current 172 * working element in the XMLDocumentWrapper component, then 173 * no new BufferNode is needed to create. 174 * This situation can only happen in the "Forwarding" mode. 175 */ 176 if ( (m_pCurrentBufferNode != NULL) && 177 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()))) 178 { 179 pBufferNode = m_pCurrentBufferNode; 180 } 181 else 182 { 183 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement()); 184 } 185 186 if (m_pNewBlocker != NULL) 187 { 188 pBufferNode->setBlocker(m_pNewBlocker); 189 190 /* 191 * If no blocking before, then notify the status change listener that 192 * the SAXEventKeeper has entered "blocking" status, during which, no 193 * SAX events will be forwarded to the next document handler. 194 */ 195 if (m_pCurrentBlockingBufferNode == NULL) 196 { 197 m_pCurrentBlockingBufferNode = pBufferNode; 198 199 if (m_xSAXEventKeeperStatusChangeListener.is()) 200 { 201 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True); 202 } 203 } 204 205 m_pNewBlocker = NULL; 206 } 207 208 if (m_vNewElementCollectors.size()>0) 209 { 210 std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin(); 211 212 for( ; ii != m_vNewElementCollectors.end(); ++ii ) 213 { 214 pBufferNode->addElementCollector(*ii); 215 } 216 217 m_vNewElementCollectors.clear(); 218 } 219 } 220 221 return pBufferNode; 222 } 223 224 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const 225 /****** SAXEventKeeperImpl/findElementMarkBuffer ***************************** 226 * 227 * NAME 228 * findElementMarkBuffer -- finds an ElementMark. 229 * 230 * SYNOPSIS 231 * pElementMark = findElementMarkBuffer( nId ); 232 * 233 * FUNCTION 234 * searches an ElementMark with the particular Id in the ElementMark 235 * list. 236 * 237 * INPUTS 238 * nId - the Id of the ElementMark to be searched. 239 * 240 * RESULT 241 * pElementMark - the ElementMark with the particular Id, or NULL when 242 * no such Id exists. 243 * 244 * HISTORY 245 * 05.01.2004 - implemented 246 * 247 * AUTHOR 248 * Michael Mi 249 * Email: michael.mi@sun.com 250 ******************************************************************************/ 251 { 252 ElementMark* pElementMark = NULL; 253 254 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin(); 255 256 for( ; ii != m_vElementMarkBuffers.end(); ++ii ) 257 { 258 if ( nId == (*ii)->getBufferId()) 259 { 260 pElementMark = (ElementMark*)*ii; 261 break; 262 } 263 } 264 265 return pElementMark; 266 } 267 268 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId) 269 /****** SAXEventKeeperImpl/removeElementMarkBuffer *************************** 270 * 271 * NAME 272 * removeElementMarkBuffer -- removes an ElementMark 273 * 274 * SYNOPSIS 275 * removeElementMarkBuffer( nId ); 276 * 277 * FUNCTION 278 * removes an ElementMark with the particular Id in the ElementMark list. 279 * 280 * INPUTS 281 * nId - the Id of the ElementMark to be removed. 282 * 283 * RESULT 284 * empty 285 * 286 * HISTORY 287 * 05.01.2004 - implemented 288 * 289 * AUTHOR 290 * Michael Mi 291 * Email: michael.mi@sun.com 292 ******************************************************************************/ 293 { 294 std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin(); 295 296 for( ; ii != m_vElementMarkBuffers.end(); ++ii ) 297 { 298 if ( nId == (*ii)->getBufferId()) 299 { 300 /* 301 * checks whether this ElementMark still in the new ElementCollect array 302 */ 303 std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin(); 304 for( ; jj != m_vNewElementCollectors.end(); ++jj ) 305 { 306 if ((*ii) == (*jj)) 307 { 308 m_vNewElementCollectors.erase(jj); 309 break; 310 } 311 } 312 313 /* 314 * checks whether this ElementMark is the new Blocker 315 */ 316 if ((*ii) == m_pNewBlocker) 317 { 318 m_pNewBlocker = NULL; 319 } 320 321 /* 322 * destory the ElementMark 323 */ 324 delete (*ii); 325 326 m_vElementMarkBuffers.erase( ii ); 327 break; 328 } 329 } 330 } 331 332 rtl::OUString SAXEventKeeperImpl::printBufferNode( 333 BufferNode* pBufferNode, sal_Int32 nIndent) const 334 /****** SAXEventKeeperImpl/printBufferNode *********************************** 335 * 336 * NAME 337 * printBufferNode -- retrieves the information of a BufferNode and its 338 * branch. 339 * 340 * SYNOPSIS 341 * info = printBufferNode( pBufferNode, nIndent ); 342 * 343 * FUNCTION 344 * all retrieved information includes: 345 * 1. whether it is the current BufferNode; 346 * 2. whether it is the current blocking BufferNode; 347 * 3. the name of the parent element; 348 * 4. the name of this element; 349 * 5. all ElementCollectors working on this BufferNode; 350 * 6. the Blocker working on this BufferNode; 351 * 7. all child BufferNodes' information. 352 * 353 * INPUTS 354 * pBufferNode - the BufferNode from where information will be retrieved. 355 * nIndent - how many space characters prefixed before the output 356 * message. 357 * 358 * RESULT 359 * info - the information string 360 * 361 * HISTORY 362 * 05.01.2004 - implemented 363 * 364 * AUTHOR 365 * Michael Mi 366 * Email: michael.mi@sun.com 367 ******************************************************************************/ 368 { 369 rtl::OUString rc; 370 371 for ( int i=0; i<nIndent; ++i ) 372 { 373 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " )); 374 } 375 376 if (pBufferNode == m_pCurrentBufferNode) 377 { 378 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" )); 379 } 380 381 if (pBufferNode == m_pCurrentBlockingBufferNode) 382 { 383 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" )); 384 } 385 386 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " )); 387 rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()); 388 389 BufferNode* pParent = (BufferNode*)pBufferNode->getParent(); 390 if (pParent != NULL) 391 { 392 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" )); 393 rc += m_xXMLDocument->getNodeName(pParent->getXMLElement()); 394 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" )); 395 } 396 397 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" )); 398 rc += pBufferNode->printChildren(); 399 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" )); 400 401 ElementMark * pBlocker = pBufferNode->getBlocker(); 402 if (pBlocker != NULL) 403 { 404 rc += rtl::OUString::valueOf( pBlocker->getBufferId() ); 405 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" )); 406 rc += rtl::OUString::valueOf( pBlocker->getSecurityId() ); 407 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" )); 408 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " )); 409 } 410 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" )); 411 412 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren(); 413 std::vector< const BufferNode* >::const_iterator jj = vChildren->begin(); 414 for( ; jj != vChildren->end(); ++jj ) 415 { 416 rc += printBufferNode((BufferNode *)*jj, nIndent+4); 417 } 418 419 delete vChildren; 420 421 return rc; 422 } 423 424 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > > 425 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const 426 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************ 427 * 428 * NAME 429 * collectChildWorkingElement -- collects a BufferNode's all child 430 * Elements. 431 * 432 * SYNOPSIS 433 * list = collectChildWorkingElement( pBufferNode ); 434 * 435 * FUNCTION 436 * see NAME. 437 * 438 * INPUTS 439 * pBufferNode - the BufferNode whose child Elements will be collected. 440 * 441 * RESULT 442 * list - the child Elements list. 443 * 444 * HISTORY 445 * 05.01.2004 - implemented 446 * 447 * AUTHOR 448 * Michael Mi 449 * Email: michael.mi@sun.com 450 ******************************************************************************/ 451 { 452 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren(); 453 454 cssu::Sequence < cssu::Reference< 455 cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size()); 456 457 std::vector< const BufferNode* >::const_iterator ii = vChildren->begin(); 458 459 sal_Int32 nIndex = 0; 460 for( ; ii != vChildren->end(); ++ii ) 461 { 462 aChildrenCollection[nIndex] = (*ii)->getXMLElement(); 463 nIndex++; 464 } 465 466 delete vChildren; 467 468 return aChildrenCollection; 469 } 470 471 void SAXEventKeeperImpl::smashBufferNode( 472 BufferNode* pBufferNode, bool bClearRoot) const 473 /****** SAXEventKeeperImpl/smashBufferNode *********************************** 474 * 475 * NAME 476 * smashBufferNode -- removes a BufferNode along with its working 477 * element. 478 * 479 * SYNOPSIS 480 * smashBufferNode( pBufferNode, bClearRoot ); 481 * 482 * FUNCTION 483 * removes the BufferNode's working element from the DOM document, while 484 * reserves all ancestor paths for its child BufferNodes. 485 * when any of the BufferNode's ancestor element is useless, removes it 486 * too. 487 * removes the BufferNode from the BufferNode tree. 488 * 489 * INPUTS 490 * pBufferNode - the BufferNode to be removed 491 * bClearRoot - whether the root element also needs to be cleared up. 492 * 493 * RESULT 494 * empty 495 * 496 * NOTES 497 * when removeing a Blocker's BufferNode, the bClearRoot flag should be 498 * true. Because a Blocker can buffer many SAX events which are not used 499 * by any other ElementCollector or Blocker. 500 * When the bClearRoot is set to true, the root BufferNode will be first 501 * cleared, with a stop flag seting at the next Blocking BufferNode. This 502 * operation can delete all useless bufferred SAX events which are only 503 * needed by the Blocker to be deleted. 504 * 505 * HISTORY 506 * 05.01.2004 - implemented 507 * 508 * AUTHOR 509 * Michael Mi 510 * Email: michael.mi@sun.com 511 ******************************************************************************/ 512 { 513 if (!pBufferNode->hasAnything()) 514 { 515 BufferNode* pParent = (BufferNode*)pBufferNode->getParent(); 516 517 /* 518 * delete the XML data 519 */ 520 if (pParent == m_pRootBufferNode) 521 { 522 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL); 523 bool bIsBlockInside = false; 524 bool bIsBlockingAfterward = false; 525 526 /* 527 * If this is a blocker, then remove any out-element data 528 * which caused by blocking. The removal process will stop 529 * at the next blocker to avoid removing any useful data. 530 */ 531 if (bClearRoot) 532 { 533 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > > 534 aChildElements = collectChildWorkingElement(m_pRootBufferNode); 535 536 /* 537 * the clearUselessData only clearup the content in the 538 * node, not the node itself. 539 */ 540 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(), 541 aChildElements, 542 bIsNotBlocking?(NULL): 543 (m_pCurrentBlockingBufferNode->getXMLElement())); 544 545 /* 546 * remove the node if it is empty, then if its parent is also 547 * empty, remove it, then if the next parent is also empty, 548 * remove it,..., until parent become null. 549 */ 550 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() ); 551 } 552 553 /* 554 * if blocking, check the relationship between this BufferNode and 555 * the current blocking BufferNode. 556 */ 557 if ( !bIsNotBlocking ) 558 { 559 /* 560 * the current blocking BufferNode is a descendant of this BufferNode. 561 */ 562 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode)); 563 564 /* 565 * the current blocking BufferNode locates behind this BufferNode in tree 566 * order. 567 */ 568 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode); 569 } 570 571 /* 572 * this BufferNode's working element needs to be deleted only when 573 * 1. there is no blocking, or 574 * 2. the current blocking BufferNode is a descendant of this BufferNode, 575 * (then in the BufferNode's working element, the useless data before the blocking 576 * element should be deleted.) or 577 * 3. the current blocking BufferNode is locates behind this BufferNode in tree, 578 * (then the useless data between the blocking element and the working element 579 * should be deleted.). 580 * Otherwise, this working element should not be deleted. 581 */ 582 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward ) 583 { 584 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > > 585 aChildElements = collectChildWorkingElement(pBufferNode); 586 587 /* 588 * the clearUselessData only clearup the content in the 589 * node, not the node itself. 590 */ 591 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(), 592 aChildElements, 593 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()): 594 (NULL)); 595 596 /* 597 * remove the node if it is empty, then if its parent is also 598 * empty, remove it, then if the next parent is also empty, 599 * remove it,..., until parent become null. 600 */ 601 m_xXMLDocument->collapse( pBufferNode->getXMLElement() ); 602 } 603 } 604 605 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode); 606 607 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren(); 608 pParent->removeChild(pBufferNode); 609 pBufferNode->setParent(NULL); 610 611 std::vector< const BufferNode * >::const_iterator ii = vChildren->begin(); 612 for( ; ii != vChildren->end(); ++ii ) 613 { 614 ((BufferNode *)(*ii))->setParent(pParent); 615 pParent->addChild(*ii, nIndex); 616 nIndex++; 617 } 618 619 delete vChildren; 620 621 /* 622 * delete the BufferNode 623 */ 624 delete pBufferNode; 625 } 626 } 627 628 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode( 629 BufferNode* pStartBufferNode) const 630 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************ 631 * 632 * NAME 633 * findNextBlockingBufferNode -- finds the next blocking BufferNode 634 * behind the particular BufferNode. 635 * 636 * SYNOPSIS 637 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode ); 638 * 639 * FUNCTION 640 * see NAME. 641 * 642 * INPUTS 643 * pStartBufferNode - the BufferNode from where to search the next 644 * blocking BufferNode. 645 * 646 * RESULT 647 * pBufferNode - the next blocking BufferNode, or NULL if no such 648 * BufferNode exists. 649 * 650 * HISTORY 651 * 05.01.2004 - implemented 652 * 653 * AUTHOR 654 * Michael Mi 655 * Email: michael.mi@sun.com 656 ******************************************************************************/ 657 { 658 BufferNode* pNext = NULL; 659 660 if (pStartBufferNode != NULL) 661 { 662 pNext = pStartBufferNode; 663 664 while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder())) 665 { 666 if (pNext->getBlocker() != NULL) 667 { 668 break; 669 } 670 } 671 } 672 673 return pNext; 674 } 675 676 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const 677 /****** SAXEventKeeperImpl/diffuse ******************************************* 678 * 679 * NAME 680 * diffuse -- diffuse the notification. 681 * 682 * SYNOPSIS 683 * diffuse( pBufferNode ); 684 * 685 * FUNCTION 686 * diffuse the collecting completion notification from the specific 687 * BufferNode along its parent link, until an ancestor which is not 688 * completely received is met. 689 * 690 * INPUTS 691 * pBufferNode - the BufferNode from which the notification will be 692 * diffused. 693 * 694 * RESULT 695 * empty 696 * 697 * HISTORY 698 * 05.01.2004 - implemented 699 * 700 * AUTHOR 701 * Michael Mi 702 * Email: michael.mi@sun.com 703 ******************************************************************************/ 704 { 705 BufferNode* pParent = pBufferNode; 706 707 while(pParent->isAllReceived()) 708 { 709 pParent->elementCollectorNotify(); 710 pParent = (BufferNode*)pParent->getParent(); 711 } 712 } 713 714 void SAXEventKeeperImpl::releaseElementMarkBuffer() 715 /****** SAXEventKeeperImpl/releaseElementMarkBuffer ************************** 716 * 717 * NAME 718 * releaseElementMarkBuffer -- releases useless ElementMarks 719 * 720 * SYNOPSIS 721 * releaseElementMarkBuffer( ); 722 * 723 * FUNCTION 724 * releases each ElementMark in the releasing list 725 * m_vReleasedElementMarkBuffers. 726 * The operation differs between an ElementCollector and a Blocker. 727 * 728 * INPUTS 729 * empty 730 * 731 * RESULT 732 * empty 733 * 734 * HISTORY 735 * 05.01.2004 - implemented 736 * 737 * AUTHOR 738 * Michael Mi 739 * Email: michael.mi@sun.com 740 ******************************************************************************/ 741 { 742 m_bIsReleasing = true; 743 while (m_vReleasedElementMarkBuffers.size()>0) 744 { 745 std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin(); 746 sal_Int32 nId = *pId; 747 m_vReleasedElementMarkBuffers.erase( pId ); 748 749 ElementMark* pElementMark = findElementMarkBuffer(nId); 750 751 if (pElementMark != NULL) 752 { 753 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR 754 == pElementMark->getType()) 755 /* 756 * it is a EC 757 */ 758 { 759 ElementCollector* pElementCollector = (ElementCollector*)pElementMark; 760 761 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority(); 762 bool bToModify = pElementCollector->getModify(); 763 764 /* 765 * Delete the EC from the buffer node. 766 */ 767 BufferNode* pBufferNode = pElementCollector->getBufferNode(); 768 pBufferNode->removeElementCollector(pElementCollector); 769 770 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY) 771 { 772 pBufferNode->notifyBranch(); 773 } 774 775 if (bToModify) 776 { 777 pBufferNode->notifyAncestor(); 778 } 779 780 /* 781 * delete the ElementMark 782 */ 783 pElementCollector = NULL; 784 pElementMark = NULL; 785 removeElementMarkBuffer(nId); 786 787 /* 788 * delete the BufferNode 789 */ 790 diffuse(pBufferNode); 791 smashBufferNode(pBufferNode, false); 792 } 793 else 794 /* 795 * it is a Blocker 796 */ 797 { 798 /* 799 * Delete the TH from the buffer node. 800 */ 801 BufferNode *pBufferNode = pElementMark->getBufferNode(); 802 pBufferNode->setBlocker(NULL); 803 804 /* 805 * If there is a following handler and no blocking now, then 806 * forward this event 807 */ 808 if (m_pCurrentBlockingBufferNode == pBufferNode) 809 { 810 /* 811 * Before forwarding, the next blocking point needs to be 812 * found. 813 */ 814 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode); 815 816 /* 817 * Forward the blocked events between these two STHs. 818 */ 819 if (m_xNextHandler.is()) 820 { 821 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode; 822 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode; 823 824 m_pCurrentBufferNode = pBufferNode; 825 m_pCurrentBlockingBufferNode = NULL; 826 827 m_bIsForwarding = true; 828 829 m_xXMLDocument->generateSAXEvents( 830 m_xNextHandler, 831 this, 832 pBufferNode->getXMLElement(), 833 (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement())); 834 835 m_bIsForwarding = false; 836 837 m_pCurrentBufferNode = pTempCurrentBufferNode; 838 if (m_pCurrentBlockingBufferNode == NULL) 839 { 840 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode; 841 } 842 } 843 844 if (m_pCurrentBlockingBufferNode == NULL && 845 m_xSAXEventKeeperStatusChangeListener.is()) 846 { 847 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False); 848 } 849 } 850 851 /* 852 * delete the ElementMark 853 */ 854 pElementMark = NULL; 855 removeElementMarkBuffer(nId); 856 857 /* 858 * delete the BufferNode 859 */ 860 diffuse(pBufferNode); 861 smashBufferNode(pBufferNode, true); 862 } 863 } 864 } 865 866 m_bIsReleasing = false; 867 868 if (!m_pRootBufferNode->hasAnything() && 869 !m_pRootBufferNode->hasChildren() && 870 m_xSAXEventKeeperStatusChangeListener.is()) 871 { 872 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True); 873 } 874 } 875 876 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId) 877 /****** SAXEventKeeperImpl/markElementMarkBuffer ***************************** 878 * 879 * NAME 880 * markElementMarkBuffer -- marks an ElementMark to be released 881 * 882 * SYNOPSIS 883 * markElementMarkBuffer( nId ); 884 * 885 * FUNCTION 886 * puts the ElementMark with the particular Id into the releasing list, 887 * checks whether the releasing process is running, if not then launch 888 * this process. 889 * 890 * INPUTS 891 * nId - the Id of the ElementMark which will be released 892 * 893 * RESULT 894 * empty 895 * 896 * HISTORY 897 * 05.01.2004 - implemented 898 * 899 * AUTHOR 900 * Michael Mi 901 * Email: michael.mi@sun.com 902 ******************************************************************************/ 903 { 904 m_vReleasedElementMarkBuffers.push_back( nId ); 905 if ( !m_bIsReleasing ) 906 { 907 releaseElementMarkBuffer(); 908 } 909 } 910 911 sal_Int32 SAXEventKeeperImpl::createElementCollector( 912 sal_Int32 nSecurityId, 913 cssxc::sax::ElementMarkPriority nPriority, 914 bool bModifyElement, 915 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener) 916 /****** SAXEventKeeperImpl/createElementCollector **************************** 917 * 918 * NAME 919 * createElementCollector -- creates a new ElementCollector on the 920 * incoming element. 921 * 922 * SYNOPSIS 923 * nId = createElementCollector( nSecurityId, nPriority, 924 * bModifyElement, 925 * xReferenceResolvedListener ); 926 * 927 * FUNCTION 928 * allocs a new Id, then create an ElementCollector with this Id value. 929 * Add the new created ElementCollector to the new ElementCollecotor list. 930 * 931 * INPUTS 932 * nSecurityId - the security Id of the new ElementCollector 933 * nPriority - the prirority of the new ElementCollector 934 * bModifyElement -whether this BufferNode will modify the content of 935 * the corresponding element it works on 936 * xReferenceResolvedListener - the listener for the new ElementCollector. 937 * 938 * RESULT 939 * nId - the Id of the new ElementCollector 940 * 941 * HISTORY 942 * 05.01.2004 - implemented 943 * 944 * AUTHOR 945 * Michael Mi 946 * Email: michael.mi@sun.com 947 ******************************************************************************/ 948 { 949 sal_Int32 nId = m_nNextElementMarkId; 950 m_nNextElementMarkId ++; 951 952 ElementCollector* pElementCollector 953 = new ElementCollector( 954 nSecurityId, 955 nId, 956 nPriority, 957 bModifyElement, 958 xReferenceResolvedListener); 959 960 m_vElementMarkBuffers.push_back( pElementCollector ); 961 962 /* 963 * All the new EC to initial EC array. 964 */ 965 m_vNewElementCollectors.push_back( pElementCollector ); 966 967 return nId; 968 } 969 970 971 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId) 972 /****** SAXEventKeeperImpl/createBlocker ************************************* 973 * 974 * NAME 975 * createBlocker -- creates a new Blocker on the incoming element. 976 * 977 * SYNOPSIS 978 * nId = createBlocker( nSecurityId ); 979 * 980 * FUNCTION 981 * see NAME. 982 * 983 * INPUTS 984 * nSecurityId - the security Id of the new Blocker 985 * 986 * RESULT 987 * nId - the Id of the new Blocker 988 * 989 * HISTORY 990 * 05.01.2004 - implemented 991 * 992 * AUTHOR 993 * Michael Mi 994 * Email: michael.mi@sun.com 995 ******************************************************************************/ 996 { 997 sal_Int32 nId = m_nNextElementMarkId; 998 m_nNextElementMarkId ++; 999 1000 OSL_ASSERT(m_pNewBlocker == NULL); 1001 1002 m_pNewBlocker = new ElementMark(nSecurityId, nId); 1003 m_vElementMarkBuffers.push_back( m_pNewBlocker ); 1004 1005 return nId; 1006 } 1007 1008 /* XSAXEventKeeper */ 1009 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( ) 1010 { 1011 return createElementCollector( 1012 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, 1013 cssxc::sax::ElementMarkPriority_AFTERMODIFY, 1014 false, 1015 NULL); 1016 } 1017 1018 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id ) 1019 { 1020 markElementMarkBuffer(id); 1021 } 1022 1023 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( ) 1024 { 1025 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID); 1026 } 1027 1028 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id ) 1029 { 1030 markElementMarkBuffer(id); 1031 } 1032 1033 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( ) 1034 { 1035 return (m_pCurrentBlockingBufferNode != NULL); 1036 } 1037 1038 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL 1039 SAXEventKeeperImpl::getElement( sal_Int32 id ) 1040 { 1041 cssu::Reference< cssxw::XXMLElementWrapper > rc; 1042 1043 ElementMark* pElementMark = findElementMarkBuffer(id); 1044 if (pElementMark != NULL) 1045 { 1046 rc = pElementMark->getBufferNode()->getXMLElement(); 1047 } 1048 1049 return rc; 1050 } 1051 1052 void SAL_CALL SAXEventKeeperImpl::setElement( 1053 sal_Int32 id, 1054 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement ) 1055 { 1056 if (aElement.is()) 1057 { 1058 m_xXMLDocument->rebuildIDLink(aElement); 1059 1060 ElementMark* pElementMark = findElementMarkBuffer(id); 1061 1062 if (pElementMark != NULL) 1063 { 1064 BufferNode* pBufferNode = pElementMark->getBufferNode(); 1065 if (pBufferNode != NULL) 1066 { 1067 bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement()); 1068 pBufferNode->setXMLElement(aElement); 1069 1070 if (bIsCurrent) 1071 { 1072 m_xXMLDocument->setCurrentElement(aElement); 1073 } 1074 } 1075 } 1076 } 1077 else 1078 { 1079 removeElementCollector( id ); 1080 } 1081 } 1082 1083 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler( 1084 const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler ) 1085 { 1086 cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler; 1087 1088 m_xNextHandler = xNewHandler; 1089 return xOldHandler; 1090 } 1091 1092 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree() 1093 { 1094 rtl::OUString rc; 1095 1096 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " )); 1097 rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size()); 1098 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " )); 1099 rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement()); 1100 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" )); 1101 rc += printBufferNode(m_pRootBufferNode, 0); 1102 1103 return rc; 1104 } 1105 1106 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode() 1107 { 1108 cssu::Reference< cssxw::XXMLElementWrapper > rc; 1109 1110 if (m_pCurrentBlockingBufferNode != NULL) 1111 { 1112 rc = m_pCurrentBlockingBufferNode->getXMLElement(); 1113 } 1114 1115 return rc; 1116 } 1117 1118 /* XSecuritySAXEventKeeper */ 1119 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector( 1120 cssxc::sax::ElementMarkPriority priority, 1121 sal_Bool modifyElement ) 1122 { 1123 return createElementCollector( 1124 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, 1125 priority, 1126 modifyElement, 1127 NULL); 1128 } 1129 1130 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector( 1131 sal_Int32 referenceId, 1132 cssxc::sax::ElementMarkPriority priority ) 1133 { 1134 sal_Int32 nId = -1; 1135 1136 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId); 1137 if (pElementCollector != NULL) 1138 { 1139 nId = m_nNextElementMarkId; 1140 m_nNextElementMarkId ++; 1141 1142 ElementCollector* pClonedOne 1143 = pElementCollector->clone(nId, priority); 1144 1145 /* 1146 * add this EC into the security data buffer array. 1147 */ 1148 m_vElementMarkBuffers.push_back(pClonedOne); 1149 1150 /* 1151 * If the reference EC is still in initial EC array, add 1152 * this cloned one into the initial EC array too. 1153 */ 1154 if (pElementCollector->getBufferNode() == NULL) 1155 { 1156 m_vNewElementCollectors.push_back(pClonedOne); 1157 } 1158 } 1159 1160 return nId; 1161 } 1162 1163 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId ) 1164 { 1165 ElementMark* pElementMark = findElementMarkBuffer(id); 1166 if (pElementMark != NULL) 1167 { 1168 pElementMark->setSecurityId(securityId); 1169 } 1170 } 1171 1172 1173 /* XReferenceResolvedBroadcaster */ 1174 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener( 1175 sal_Int32 referenceId, 1176 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener ) 1177 { 1178 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId); 1179 if (pElementCollector != NULL) 1180 { 1181 pElementCollector->setReferenceResolvedListener(listener); 1182 } 1183 } 1184 1185 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener( 1186 sal_Int32 /*referenceId*/, 1187 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&) 1188 { 1189 } 1190 1191 /* XSAXEventKeeperStatusChangeBroadcaster */ 1192 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener( 1193 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener ) 1194 { 1195 m_xSAXEventKeeperStatusChangeListener = listener; 1196 } 1197 1198 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener( 1199 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&) 1200 { 1201 } 1202 1203 /* XDocumentHandler */ 1204 void SAL_CALL SAXEventKeeperImpl::startDocument( ) 1205 { 1206 if ( m_xNextHandler.is()) 1207 { 1208 m_xNextHandler->startDocument(); 1209 } 1210 } 1211 1212 void SAL_CALL SAXEventKeeperImpl::endDocument( ) 1213 { 1214 if ( m_xNextHandler.is()) 1215 { 1216 m_xNextHandler->endDocument(); 1217 } 1218 } 1219 1220 void SAL_CALL SAXEventKeeperImpl::startElement( 1221 const rtl::OUString& aName, 1222 const cssu::Reference< cssxs::XAttributeList >& xAttribs ) 1223 { 1224 /* 1225 * If there is a following handler and no blocking now, then 1226 * forward this event 1227 */ 1228 if ((m_pCurrentBlockingBufferNode == NULL) && 1229 (m_xNextHandler.is()) && 1230 (!m_bIsForwarding) && 1231 (m_pNewBlocker == NULL)) 1232 { 1233 m_xNextHandler->startElement(aName, xAttribs); 1234 } 1235 1236 /* 1237 * If not forwarding, buffer this startElement. 1238 */ 1239 if (!m_bIsForwarding) 1240 { 1241 #ifndef _USECOMPRESSEDDOCUMENTHANDLER 1242 m_xDocumentHandler->startElement(aName, xAttribs); 1243 #else 1244 sal_Int32 nLength = xAttribs->getLength(); 1245 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength); 1246 1247 for ( int i = 0; i<nLength; ++i ) 1248 { 1249 aAttributes[i].sName = xAttribs->getNameByIndex((short)i); 1250 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i); 1251 } 1252 1253 m_xCompressedDocumentHandler->_startElement(aName, aAttributes); 1254 #endif 1255 1256 } 1257 1258 BufferNode* pBufferNode = addNewElementMarkBuffers(); 1259 if (pBufferNode != NULL) 1260 { 1261 setCurrentBufferNode(pBufferNode); 1262 } 1263 } 1264 1265 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName ) 1266 { 1267 sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()); 1268 1269 /* 1270 * If there is a following handler and no blocking now, then 1271 * forward this event 1272 */ 1273 if ((m_pCurrentBlockingBufferNode == NULL) && 1274 (m_xNextHandler.is()) && 1275 (!m_bIsForwarding)) 1276 { 1277 m_xNextHandler->endElement(aName); 1278 } 1279 1280 if ((m_pCurrentBlockingBufferNode != NULL) || 1281 (m_pCurrentBufferNode != m_pRootBufferNode) || 1282 (!m_xXMLDocument->isCurrentElementEmpty())) 1283 { 1284 if (!m_bIsForwarding) 1285 { 1286 #ifndef _USECOMPRESSEDDOCUMENTHANDLER 1287 m_xDocumentHandler->endElement(aName); 1288 #else 1289 m_xCompressedDocumentHandler->_endElement(aName); 1290 #endif 1291 } 1292 1293 /* 1294 * If the current buffer node has not notified yet, and 1295 * the current buffer node is waiting for the current element, 1296 * then let it notify. 1297 */ 1298 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode)) 1299 { 1300 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode; 1301 m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent(); 1302 1303 pOldCurrentBufferNode->setReceivedAll(); 1304 1305 if ((m_pCurrentBufferNode == m_pRootBufferNode) && 1306 m_xSAXEventKeeperStatusChangeListener.is()) 1307 { 1308 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False); 1309 } 1310 } 1311 } 1312 else 1313 { 1314 if (!m_bIsForwarding) 1315 { 1316 m_xXMLDocument->removeCurrentElement(); 1317 } 1318 } 1319 } 1320 1321 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars ) 1322 { 1323 if (!m_bIsForwarding) 1324 { 1325 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is()) 1326 { 1327 m_xNextHandler->characters(aChars); 1328 } 1329 1330 if ((m_pCurrentBlockingBufferNode != NULL) || 1331 (m_pCurrentBufferNode != m_pRootBufferNode)) 1332 { 1333 #ifndef _USECOMPRESSEDDOCUMENTHANDLER 1334 m_xDocumentHandler->characters(aChars); 1335 #else 1336 m_xCompressedDocumentHandler->_characters(aChars); 1337 #endif 1338 } 1339 } 1340 } 1341 1342 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces ) 1343 { 1344 characters( aWhitespaces ); 1345 } 1346 1347 void SAL_CALL SAXEventKeeperImpl::processingInstruction( 1348 const rtl::OUString& aTarget, const rtl::OUString& aData ) 1349 { 1350 if (!m_bIsForwarding) 1351 { 1352 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is()) 1353 { 1354 m_xNextHandler->processingInstruction(aTarget, aData); 1355 } 1356 1357 if ((m_pCurrentBlockingBufferNode != NULL) || 1358 (m_pCurrentBufferNode != m_pRootBufferNode)) 1359 { 1360 #ifndef _USECOMPRESSEDDOCUMENTHANDLER 1361 m_xDocumentHandler->processingInstruction(aTarget, aData); 1362 #else 1363 m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData); 1364 #endif 1365 } 1366 } 1367 } 1368 1369 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&) 1370 { 1371 } 1372 1373 /* XInitialization */ 1374 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments ) 1375 { 1376 OSL_ASSERT(aArguments.getLength() == 1); 1377 1378 aArguments[0] >>= m_xXMLDocument; 1379 m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >( 1380 m_xXMLDocument, cssu::UNO_QUERY ); 1381 m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >( 1382 m_xXMLDocument, cssu::UNO_QUERY ); 1383 1384 m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement()); 1385 m_pCurrentBufferNode = m_pRootBufferNode; 1386 } 1387 1388 rtl::OUString SAXEventKeeperImpl_getImplementationName () 1389 { 1390 return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) ); 1391 } 1392 1393 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName ) 1394 { 1395 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME )); 1396 } 1397 1398 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( ) 1399 { 1400 cssu::Sequence < rtl::OUString > aRet(1); 1401 rtl::OUString* pArray = aRet.getArray(); 1402 pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); 1403 return aRet; 1404 } 1405 #undef SERVICE_NAME 1406 1407 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance( 1408 const cssu::Reference< cssl::XMultiServiceFactory > &) 1409 { 1410 return (cppu::OWeakObject*) new SAXEventKeeperImpl(); 1411 } 1412 1413 /* XServiceInfo */ 1414 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( ) 1415 { 1416 return SAXEventKeeperImpl_getImplementationName(); 1417 } 1418 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName ) 1419 { 1420 return SAXEventKeeperImpl_supportsService( rServiceName ); 1421 } 1422 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( ) 1423 { 1424 return SAXEventKeeperImpl_getSupportedServiceNames(); 1425 } 1426