1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <framework/saxeventkeeperimpl.hxx>
22 #include "buffernode.hxx"
23 #include "elementmark.hxx"
24 #include "elementcollector.hxx"
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
27 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <osl/diagnose.h>
31 namespace cssu
= com::sun::star::uno
;
32 namespace cssl
= com::sun::star::lang
;
33 namespace cssxc
= com::sun::star::xml::crypto
;
34 namespace cssxcsax
= com::sun::star::xml::csax
;
35 namespace cssxw
= com::sun::star::xml::wrapper
;
36 namespace cssxs
= com::sun::star::xml::sax
;
38 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
40 SAXEventKeeperImpl::SAXEventKeeperImpl( )
41 :m_pRootBufferNode(nullptr),
42 m_pCurrentBufferNode(nullptr),
43 m_nNextElementMarkId(1),
44 m_pNewBlocker(nullptr),
45 m_pCurrentBlockingBufferNode(nullptr),
46 m_bIsReleasing(false),
47 m_bIsForwarding(false)
49 m_vElementMarkBuffers
.reserve(2);
50 m_vNewElementCollectors
.reserve(2);
51 m_vReleasedElementMarkBuffers
.reserve(2);
54 SAXEventKeeperImpl::~SAXEventKeeperImpl()
57 * delete the BufferNode tree
59 if (m_pRootBufferNode
!= nullptr)
61 m_pRootBufferNode
->freeAllChildren();
62 delete m_pRootBufferNode
;
65 m_pRootBufferNode
= m_pCurrentBufferNode
= m_pCurrentBlockingBufferNode
= nullptr;
68 * delete all unfreed ElementMarks
70 m_vNewElementCollectors
.clear();
71 m_pNewBlocker
= nullptr;
74 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode
* pBufferNode
)
75 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
78 * setCurrentBufferNode -- set a new active BufferNode.
81 * setCurrentBufferNode( pBufferNode );
84 * connects this BufferNode into the BufferNode tree as a child of the
85 * current active BufferNode. Then makes this BufferNode as the current
87 * If the previous active BufferNode points to the root
88 * BufferNode, which means that no buffering operation was proceeding,
89 * then notifies the status change listener that buffering operation
93 * pBufferNode - a BufferNode which will be the new active BufferNode
94 ******************************************************************************/
96 if (pBufferNode
!= m_pCurrentBufferNode
)
98 if ( m_pCurrentBufferNode
== m_pRootBufferNode
&&
99 m_xSAXEventKeeperStatusChangeListener
.is())
101 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(true);
104 if (pBufferNode
->getParent() == nullptr)
106 m_pCurrentBufferNode
->addChild(pBufferNode
);
107 pBufferNode
->setParent(m_pCurrentBufferNode
);
110 m_pCurrentBufferNode
= pBufferNode
;
114 BufferNode
* SAXEventKeeperImpl::addNewElementMarkBuffers()
115 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
118 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
121 * pBufferNode = addNewElementMarkBuffers( );
124 * if there are new ElementCollector or new Blocker to be added, then
125 * connect all of them with the current BufferNode. In case of the
126 * current BufferNode doesn't exist, creates one.
127 * Clears up the new ElementCollector list and the new Blocker pointer.
130 * pBufferNode - the BufferNode that has been connected with both new
131 * ElementCollectors and new Blocker.
132 ******************************************************************************/
134 BufferNode
* pBufferNode
= nullptr;
136 if (m_pNewBlocker
|| !m_vNewElementCollectors
.empty() )
139 * When the current BufferNode is right pointing to the current
140 * working element in the XMLDocumentWrapper component, then
141 * no new BufferNode is needed to create.
142 * This situation can only happen in the "Forwarding" mode.
144 if ( (m_pCurrentBufferNode
!= nullptr) &&
145 (m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement())))
147 pBufferNode
= m_pCurrentBufferNode
;
151 pBufferNode
= new BufferNode(m_xXMLDocument
->getCurrentElement());
154 if (m_pNewBlocker
!= nullptr)
156 pBufferNode
->setBlocker(m_pNewBlocker
);
159 * If no blocking before, then notify the status change listener that
160 * the SAXEventKeeper has entered "blocking" status, during which, no
161 * SAX events will be forwarded to the next document handler.
163 if (m_pCurrentBlockingBufferNode
== nullptr)
165 m_pCurrentBlockingBufferNode
= pBufferNode
;
167 if (m_xSAXEventKeeperStatusChangeListener
.is())
169 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(true);
173 m_pNewBlocker
= nullptr;
176 if (!m_vNewElementCollectors
.empty())
178 for( auto ii
= m_vNewElementCollectors
.begin();
179 ii
!= m_vNewElementCollectors
.end(); ++ii
)
181 pBufferNode
->addElementCollector(*ii
);
184 m_vNewElementCollectors
.clear();
191 ElementMark
* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId
) const
192 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
195 * findElementMarkBuffer -- finds an ElementMark.
198 * pElementMark = findElementMarkBuffer( nId );
201 * searches an ElementMark with the particular Id in the ElementMark
205 * nId - the Id of the ElementMark to be searched.
208 * pElementMark - the ElementMark with the particular Id, or NULL when
210 ******************************************************************************/
212 ElementMark
* pElementMark
= nullptr;
214 for( auto&& ii
: m_vElementMarkBuffers
)
216 if ( nId
== ii
->getBufferId())
218 pElementMark
= const_cast<ElementMark
*>(ii
.get());
226 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId
)
227 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
230 * removeElementMarkBuffer -- removes an ElementMark
233 * removeElementMarkBuffer( nId );
236 * removes an ElementMark with the particular Id in the ElementMark list.
239 * nId - the Id of the ElementMark to be removed.
240 ******************************************************************************/
242 for( auto ii
= m_vElementMarkBuffers
.begin();
243 ii
!= m_vElementMarkBuffers
.end(); ++ii
)
245 if ( nId
== (*ii
)->getBufferId())
248 * checks whether this ElementMark still in the new ElementCollect array
250 for( auto jj
= m_vNewElementCollectors
.begin();
251 jj
!= m_vNewElementCollectors
.end(); ++jj
)
253 if (ii
->get() == (*jj
))
255 m_vNewElementCollectors
.erase(jj
);
261 * checks whether this ElementMark is the new Blocker
263 if (ii
->get() == m_pNewBlocker
)
265 m_pNewBlocker
= nullptr;
268 m_vElementMarkBuffers
.erase( ii
);
274 OUString
SAXEventKeeperImpl::printBufferNode(
275 BufferNode
const * pBufferNode
, sal_Int32 nIndent
) const
276 /****** SAXEventKeeperImpl/printBufferNode ***********************************
279 * printBufferNode -- retrieves the information of a BufferNode and its
283 * info = printBufferNode( pBufferNode, nIndent );
286 * all retrieved information includes:
287 * 1. whether it is the current BufferNode;
288 * 2. whether it is the current blocking BufferNode;
289 * 3. the name of the parent element;
290 * 4. the name of this element;
291 * 5. all ElementCollectors working on this BufferNode;
292 * 6. the Blocker working on this BufferNode;
293 * 7. all child BufferNodes' information.
296 * pBufferNode - the BufferNode from where information will be retrieved.
297 * nIndent - how many space characters prefixed before the output
301 * info - the information string
302 ******************************************************************************/
306 for ( int i
=0; i
<nIndent
; ++i
)
311 if (pBufferNode
== m_pCurrentBufferNode
)
316 if (pBufferNode
== m_pCurrentBlockingBufferNode
)
321 rc
+= " " + m_xXMLDocument
->getNodeName(pBufferNode
->getXMLElement());
323 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
324 if (pParent
!= nullptr)
326 rc
+= "[" + m_xXMLDocument
->getNodeName(pParent
->getXMLElement()) + "]";
329 rc
+= ":EC=" + pBufferNode
->printChildren() + " BR=";
331 ElementMark
* pBlocker
= pBufferNode
->getBlocker();
332 if (pBlocker
!= nullptr)
334 rc
+= OUString::number( pBlocker
->getBufferId() ) + "(SecId="
335 + OUString::number( pBlocker
->getSecurityId() ) + ") ";
339 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
340 for( auto jj
= vChildren
->begin();
341 jj
!= vChildren
->end(); ++jj
)
343 rc
+= printBufferNode(*jj
, nIndent
+4);
351 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
352 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode
const * pBufferNode
)
353 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
356 * collectChildWorkingElement -- collects a BufferNode's all child
360 * list = collectChildWorkingElement( pBufferNode );
363 * pBufferNode - the BufferNode whose child Elements will be collected.
366 * list - the child Elements list.
367 ******************************************************************************/
369 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
371 cssu::Sequence
< cssu::Reference
<
372 cssxw::XXMLElementWrapper
> > aChildrenCollection ( vChildren
->size());
374 sal_Int32 nIndex
= 0;
375 for( auto ii
= vChildren
->begin();
376 ii
!= vChildren
->end(); ++ii
)
378 aChildrenCollection
[nIndex
] = (*ii
)->getXMLElement();
384 return aChildrenCollection
;
387 void SAXEventKeeperImpl::smashBufferNode(
388 BufferNode
* pBufferNode
, bool bClearRoot
) const
389 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
392 * smashBufferNode -- removes a BufferNode along with its working
396 * smashBufferNode( pBufferNode, bClearRoot );
399 * removes the BufferNode's working element from the DOM document, while
400 * reserves all ancestor paths for its child BufferNodes.
401 * when any of the BufferNode's ancestor element is useless, removes it
403 * removes the BufferNode from the BufferNode tree.
406 * pBufferNode - the BufferNode to be removed
407 * bClearRoot - whether the root element also needs to be cleared up.
410 * when removing a Blocker's BufferNode, the bClearRoot flag should be
411 * true. Because a Blocker can buffer many SAX events which are not used
412 * by any other ElementCollector or Blocker.
413 * When the bClearRoot is set to true, the root BufferNode will be first
414 * cleared, with a stop flag setting at the next Blocking BufferNode. This
415 * operation can delete all useless bufferred SAX events which are only
416 * needed by the Blocker to be deleted.
417 ******************************************************************************/
419 if (!pBufferNode
->hasAnything())
421 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
424 * delete the XML data
426 if (pParent
== m_pRootBufferNode
)
428 bool bIsNotBlocking
= (m_pCurrentBlockingBufferNode
== nullptr);
429 bool bIsBlockInside
= false;
430 bool bIsBlockingAfterward
= false;
433 * If this is a blocker, then remove any out-element data
434 * which caused by blocking. The removal process will stop
435 * at the next blocker to avoid removing any useful data.
439 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
440 aChildElements
= collectChildWorkingElement(m_pRootBufferNode
);
443 * the clearUselessData only clearup the content in the
444 * node, not the node itself.
446 m_xXMLDocument
->clearUselessData(m_pRootBufferNode
->getXMLElement(),
448 bIsNotBlocking
?(nullptr):
449 (m_pCurrentBlockingBufferNode
->getXMLElement()));
452 * remove the node if it is empty, then if its parent is also
453 * empty, remove it, then if the next parent is also empty,
454 * remove it,..., until parent become null.
456 m_xXMLDocument
->collapse( m_pRootBufferNode
->getXMLElement() );
460 * if blocking, check the relationship between this BufferNode and
461 * the current blocking BufferNode.
463 if ( !bIsNotBlocking
)
466 * the current blocking BufferNode is a descendant of this BufferNode.
468 bIsBlockInside
= (nullptr != pBufferNode
->isAncestor(m_pCurrentBlockingBufferNode
));
471 * the current blocking BufferNode locates behind this BufferNode in tree
474 bIsBlockingAfterward
= pBufferNode
->isPrevious(m_pCurrentBlockingBufferNode
);
478 * this BufferNode's working element needs to be deleted only when
479 * 1. there is no blocking, or
480 * 2. the current blocking BufferNode is a descendant of this BufferNode,
481 * (then in the BufferNode's working element, the useless data before the blocking
482 * element should be deleted.) or
483 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
484 * (then the useless data between the blocking element and the working element
485 * should be deleted.).
486 * Otherwise, this working element should not be deleted.
488 if ( bIsNotBlocking
|| bIsBlockInside
|| bIsBlockingAfterward
)
490 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
491 aChildElements
= collectChildWorkingElement(pBufferNode
);
494 * the clearUselessData only clearup the content in the
495 * node, not the node itself.
497 m_xXMLDocument
->clearUselessData(pBufferNode
->getXMLElement(),
499 bIsBlockInside
?(m_pCurrentBlockingBufferNode
->getXMLElement()):
503 * remove the node if it is empty, then if its parent is also
504 * empty, remove it, then if the next parent is also empty,
505 * remove it,..., until parent become null.
507 m_xXMLDocument
->collapse( pBufferNode
->getXMLElement() );
511 sal_Int32 nIndex
= pParent
->indexOfChild(pBufferNode
);
513 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
514 pParent
->removeChild(pBufferNode
);
515 pBufferNode
->setParent(nullptr);
517 for( auto ii
= vChildren
->begin();
518 ii
!= vChildren
->end(); ++ii
)
520 const_cast<BufferNode
*>(*ii
)->setParent(pParent
);
521 pParent
->addChild(*ii
, nIndex
);
528 * delete the BufferNode
534 BufferNode
* SAXEventKeeperImpl::findNextBlockingBufferNode(
535 BufferNode
* pStartBufferNode
)
536 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
539 * findNextBlockingBufferNode -- finds the next blocking BufferNode
540 * behind the particular BufferNode.
543 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
546 * pStartBufferNode - the BufferNode from where to search the next
547 * blocking BufferNode.
550 * pBufferNode - the next blocking BufferNode, or NULL if no such
552 ******************************************************************************/
554 BufferNode
* pNext
= nullptr;
556 if (pStartBufferNode
!= nullptr)
558 pNext
= pStartBufferNode
;
560 while (nullptr != (pNext
= const_cast<BufferNode
*>(pNext
->getNextNodeByTreeOrder())))
562 if (pNext
->getBlocker() != nullptr)
572 void SAXEventKeeperImpl::diffuse(BufferNode
* pBufferNode
)
573 /****** SAXEventKeeperImpl/diffuse *******************************************
576 * diffuse -- diffuse the notification.
579 * diffuse( pBufferNode );
582 * diffuse the collecting completion notification from the specific
583 * BufferNode along its parent link, until an ancestor which is not
584 * completely received is met.
587 * pBufferNode - the BufferNode from which the notification will be
589 ******************************************************************************/
591 BufferNode
* pParent
= pBufferNode
;
593 while(pParent
->isAllReceived())
595 pParent
->elementCollectorNotify();
596 pParent
= const_cast<BufferNode
*>(pParent
->getParent());
600 void SAXEventKeeperImpl::releaseElementMarkBuffer()
601 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
604 * releaseElementMarkBuffer -- releases useless ElementMarks
607 * releaseElementMarkBuffer( );
610 * releases each ElementMark in the releasing list
611 * m_vReleasedElementMarkBuffers.
612 * The operation differs between an ElementCollector and a Blocker.
613 ******************************************************************************/
615 m_bIsReleasing
= true;
616 while (!m_vReleasedElementMarkBuffers
.empty())
618 auto pId
= m_vReleasedElementMarkBuffers
.begin();
619 sal_Int32 nId
= *pId
;
620 m_vReleasedElementMarkBuffers
.erase( pId
);
622 ElementMark
* pElementMark
= findElementMarkBuffer(nId
);
624 if (pElementMark
!= nullptr)
626 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
627 == pElementMark
->getType())
632 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(pElementMark
);
634 cssxc::sax::ElementMarkPriority nPriority
= pElementCollector
->getPriority();
636 * Delete the EC from the buffer node.
638 BufferNode
* pBufferNode
= pElementCollector
->getBufferNode();
639 pBufferNode
->removeElementCollector(pElementCollector
);
641 if ( nPriority
== cssxc::sax::ElementMarkPriority_BEFOREMODIFY
)
643 pBufferNode
->notifyBranch();
647 * delete the ElementMark
649 pElementCollector
= nullptr;
650 pElementMark
= nullptr;
651 removeElementMarkBuffer(nId
);
654 * delete the BufferNode
656 diffuse(pBufferNode
);
657 smashBufferNode(pBufferNode
, false);
665 * Delete the TH from the buffer node.
667 BufferNode
*pBufferNode
= pElementMark
->getBufferNode();
668 pBufferNode
->setBlocker(nullptr);
671 * If there is a following handler and no blocking now, then
674 if (m_pCurrentBlockingBufferNode
== pBufferNode
)
677 * Before forwarding, the next blocking point needs to be
680 m_pCurrentBlockingBufferNode
= findNextBlockingBufferNode(pBufferNode
);
683 * Forward the blocked events between these two STHs.
685 if (m_xNextHandler
.is())
687 BufferNode
* pTempCurrentBufferNode
= m_pCurrentBufferNode
;
688 BufferNode
* pTempCurrentBlockingBufferNode
= m_pCurrentBlockingBufferNode
;
690 m_pCurrentBufferNode
= pBufferNode
;
691 m_pCurrentBlockingBufferNode
= nullptr;
693 m_bIsForwarding
= true;
695 m_xXMLDocument
->generateSAXEvents(
698 pBufferNode
->getXMLElement(),
699 (pTempCurrentBlockingBufferNode
== nullptr)?nullptr:(pTempCurrentBlockingBufferNode
->getXMLElement()));
701 m_bIsForwarding
= false;
703 m_pCurrentBufferNode
= pTempCurrentBufferNode
;
704 if (m_pCurrentBlockingBufferNode
== nullptr)
706 m_pCurrentBlockingBufferNode
= pTempCurrentBlockingBufferNode
;
710 if (m_pCurrentBlockingBufferNode
== nullptr &&
711 m_xSAXEventKeeperStatusChangeListener
.is())
713 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(false);
718 * delete the ElementMark
720 pElementMark
= nullptr;
721 removeElementMarkBuffer(nId
);
724 * delete the BufferNode
726 diffuse(pBufferNode
);
727 smashBufferNode(pBufferNode
, true);
732 m_bIsReleasing
= false;
734 if (!m_pRootBufferNode
->hasAnything() &&
735 !m_pRootBufferNode
->hasChildren() &&
736 m_xSAXEventKeeperStatusChangeListener
.is())
738 m_xSAXEventKeeperStatusChangeListener
->bufferStatusChanged(true);
742 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId
)
743 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
746 * markElementMarkBuffer -- marks an ElementMark to be released
749 * markElementMarkBuffer( nId );
752 * puts the ElementMark with the particular Id into the releasing list,
753 * checks whether the releasing process is running, if not then launch
757 * nId - the Id of the ElementMark which will be released
758 ******************************************************************************/
760 m_vReleasedElementMarkBuffers
.push_back( nId
);
761 if ( !m_bIsReleasing
)
763 releaseElementMarkBuffer();
767 sal_Int32
SAXEventKeeperImpl::createElementCollector(
768 cssxc::sax::ElementMarkPriority nPriority
,
770 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& xReferenceResolvedListener
)
771 /****** SAXEventKeeperImpl/createElementCollector ****************************
774 * createElementCollector -- creates a new ElementCollector on the
778 * nId = createElementCollector( nSecurityId, nPriority,
780 * xReferenceResolvedListener );
783 * allocs a new Id, then create an ElementCollector with this Id value.
784 * Add the new created ElementCollector to the new ElementCollecotor list.
787 * nPriority - the priority of the new ElementCollector
788 * bModifyElement -whether this BufferNode will modify the content of
789 * the corresponding element it works on
790 * xReferenceResolvedListener - the listener for the new ElementCollector.
793 * nId - the Id of the new ElementCollector
794 ******************************************************************************/
796 sal_Int32 nId
= m_nNextElementMarkId
;
797 m_nNextElementMarkId
++;
799 ElementCollector
* pElementCollector
800 = new ElementCollector(
804 xReferenceResolvedListener
);
806 m_vElementMarkBuffers
.push_back(
807 std::unique_ptr
<const ElementMark
>(pElementCollector
));
810 * All the new EC to initial EC array.
812 m_vNewElementCollectors
.push_back( pElementCollector
);
818 sal_Int32
SAXEventKeeperImpl::createBlocker()
819 /****** SAXEventKeeperImpl/createBlocker *************************************
822 * createBlocker -- creates a new Blocker on the incoming element.
825 * nId = createBlocker( nSecurityId );
828 * nId - the Id of the new Blocker
829 ******************************************************************************/
831 sal_Int32 nId
= m_nNextElementMarkId
;
832 m_nNextElementMarkId
++;
834 OSL_ASSERT(m_pNewBlocker
== nullptr);
836 m_pNewBlocker
= new ElementMark(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
, nId
);
837 m_vElementMarkBuffers
.push_back(
838 std::unique_ptr
<const ElementMark
>(m_pNewBlocker
));
843 /* XSAXEventKeeper */
844 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addElementCollector( )
846 return createElementCollector(
847 cssxc::sax::ElementMarkPriority_AFTERMODIFY
,
852 void SAL_CALL
SAXEventKeeperImpl::removeElementCollector( sal_Int32 id
)
854 markElementMarkBuffer(id
);
857 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addBlocker( )
859 return createBlocker();
862 void SAL_CALL
SAXEventKeeperImpl::removeBlocker( sal_Int32 id
)
864 markElementMarkBuffer(id
);
867 sal_Bool SAL_CALL
SAXEventKeeperImpl::isBlocking( )
869 return (m_pCurrentBlockingBufferNode
!= nullptr);
872 cssu::Reference
< cssxw::XXMLElementWrapper
> SAL_CALL
873 SAXEventKeeperImpl::getElement( sal_Int32 id
)
875 cssu::Reference
< cssxw::XXMLElementWrapper
> rc
;
877 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
878 if (pElementMark
!= nullptr)
880 rc
= pElementMark
->getBufferNode()->getXMLElement();
886 void SAL_CALL
SAXEventKeeperImpl::setElement(
888 const cssu::Reference
< cssxw::XXMLElementWrapper
>& aElement
)
892 m_xXMLDocument
->rebuildIDLink(aElement
);
894 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
896 if (pElementMark
!= nullptr)
898 BufferNode
* pBufferNode
= pElementMark
->getBufferNode();
899 if (pBufferNode
!= nullptr)
901 const bool bIsCurrent
= m_xXMLDocument
->isCurrent(pBufferNode
->getXMLElement());
902 pBufferNode
->setXMLElement(aElement
);
906 m_xXMLDocument
->setCurrentElement(aElement
);
913 removeElementCollector( id
);
917 cssu::Reference
< cssxs::XDocumentHandler
> SAL_CALL
SAXEventKeeperImpl::setNextHandler(
918 const cssu::Reference
< cssxs::XDocumentHandler
>& xNewHandler
)
920 cssu::Reference
< cssxs::XDocumentHandler
> xOldHandler
= m_xNextHandler
;
922 m_xNextHandler
= xNewHandler
;
926 OUString SAL_CALL
SAXEventKeeperImpl::printBufferNodeTree()
930 rc
+= "ElementMarkBuffers: size = "
931 + OUString::number(m_vElementMarkBuffers
.size())
932 + "\nCurrentBufferNode: "
933 + m_xXMLDocument
->getNodeName(m_pCurrentBufferNode
->getXMLElement())
934 + "\n" + printBufferNode(m_pRootBufferNode
, 0);
939 cssu::Reference
< cssxw::XXMLElementWrapper
> SAL_CALL
SAXEventKeeperImpl::getCurrentBlockingNode()
941 cssu::Reference
< cssxw::XXMLElementWrapper
> rc
;
943 if (m_pCurrentBlockingBufferNode
!= nullptr)
945 rc
= m_pCurrentBlockingBufferNode
->getXMLElement();
951 /* XSecuritySAXEventKeeper */
952 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addSecurityElementCollector(
953 cssxc::sax::ElementMarkPriority priority
,
954 sal_Bool modifyElement
)
956 return createElementCollector(
962 void SAL_CALL
SAXEventKeeperImpl::setSecurityId( sal_Int32 id
, sal_Int32 securityId
)
964 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
965 if (pElementMark
!= nullptr)
967 pElementMark
->setSecurityId(securityId
);
972 /* XReferenceResolvedBroadcaster */
973 void SAL_CALL
SAXEventKeeperImpl::addReferenceResolvedListener(
974 sal_Int32 referenceId
,
975 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& listener
)
977 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(findElementMarkBuffer(referenceId
));
978 if (pElementCollector
!= nullptr)
980 pElementCollector
->setReferenceResolvedListener(listener
);
984 void SAL_CALL
SAXEventKeeperImpl::removeReferenceResolvedListener(
985 sal_Int32
/*referenceId*/,
986 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>&)
990 /* XSAXEventKeeperStatusChangeBroadcaster */
991 void SAL_CALL
SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
992 const cssu::Reference
< cssxc::sax::XSAXEventKeeperStatusChangeListener
>& listener
)
994 m_xSAXEventKeeperStatusChangeListener
= listener
;
997 void SAL_CALL
SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
998 const cssu::Reference
< cssxc::sax::XSAXEventKeeperStatusChangeListener
>&)
1002 /* XDocumentHandler */
1003 void SAL_CALL
SAXEventKeeperImpl::startDocument( )
1005 if ( m_xNextHandler
.is())
1007 m_xNextHandler
->startDocument();
1011 void SAL_CALL
SAXEventKeeperImpl::endDocument( )
1013 if ( m_xNextHandler
.is())
1015 m_xNextHandler
->endDocument();
1019 void SAL_CALL
SAXEventKeeperImpl::startElement(
1020 const OUString
& aName
,
1021 const cssu::Reference
< cssxs::XAttributeList
>& xAttribs
)
1024 * If there is a following handler and no blocking now, then
1025 * forward this event
1027 if ((m_pCurrentBlockingBufferNode
== nullptr) &&
1028 (m_xNextHandler
.is()) &&
1029 (!m_bIsForwarding
) &&
1030 (m_pNewBlocker
== nullptr))
1032 m_xNextHandler
->startElement(aName
, xAttribs
);
1035 * If not forwarding, buffer this startElement.
1037 if (!m_bIsForwarding
)
1039 sal_Int32 nLength
= xAttribs
->getLength();
1040 cssu::Sequence
< cssxcsax::XMLAttribute
> aAttributes (nLength
);
1042 for ( int i
= 0; i
<nLength
; ++i
)
1044 aAttributes
[i
].sName
= xAttribs
->getNameByIndex((short)i
);
1045 aAttributes
[i
].sValue
=xAttribs
->getValueByIndex((short)i
);
1048 m_xCompressedDocumentHandler
->compressedStartElement(aName
, aAttributes
);
1051 BufferNode
* pBufferNode
= addNewElementMarkBuffers();
1052 if (pBufferNode
!= nullptr)
1054 setCurrentBufferNode(pBufferNode
);
1058 void SAL_CALL
SAXEventKeeperImpl::endElement( const OUString
& aName
)
1060 const bool bIsCurrent
= m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement());
1063 * If there is a following handler and no blocking now, then
1064 * forward this event
1066 if ((m_pCurrentBlockingBufferNode
== nullptr) &&
1067 (m_xNextHandler
.is()) &&
1070 m_xNextHandler
->endElement(aName
);
1073 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1074 (m_pCurrentBufferNode
!= m_pRootBufferNode
) ||
1075 (!m_xXMLDocument
->isCurrentElementEmpty()))
1077 if (!m_bIsForwarding
)
1079 m_xCompressedDocumentHandler
->compressedEndElement(aName
);
1083 * If the current buffer node has not notified yet, and
1084 * the current buffer node is waiting for the current element,
1085 * then let it notify.
1087 if (bIsCurrent
&& (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1089 BufferNode
* pOldCurrentBufferNode
= m_pCurrentBufferNode
;
1090 m_pCurrentBufferNode
= const_cast<BufferNode
*>(m_pCurrentBufferNode
->getParent());
1092 pOldCurrentBufferNode
->setReceivedAll();
1094 if ((m_pCurrentBufferNode
== m_pRootBufferNode
) &&
1095 m_xSAXEventKeeperStatusChangeListener
.is())
1097 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(false);
1103 if (!m_bIsForwarding
)
1105 m_xXMLDocument
->removeCurrentElement();
1110 void SAL_CALL
SAXEventKeeperImpl::characters( const OUString
& aChars
)
1112 if (!m_bIsForwarding
)
1114 if ((m_pCurrentBlockingBufferNode
== nullptr) && m_xNextHandler
.is())
1116 m_xNextHandler
->characters(aChars
);
1119 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1120 (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1122 m_xCompressedDocumentHandler
->compressedCharacters(aChars
);
1127 void SAL_CALL
SAXEventKeeperImpl::ignorableWhitespace( const OUString
& aWhitespaces
)
1129 characters( aWhitespaces
);
1132 void SAL_CALL
SAXEventKeeperImpl::processingInstruction(
1133 const OUString
& aTarget
, const OUString
& aData
)
1135 if (!m_bIsForwarding
)
1137 if ((m_pCurrentBlockingBufferNode
== nullptr) && m_xNextHandler
.is())
1139 m_xNextHandler
->processingInstruction(aTarget
, aData
);
1142 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1143 (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1145 m_xCompressedDocumentHandler
->compressedProcessingInstruction(aTarget
, aData
);
1150 void SAL_CALL
SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference
< cssxs::XLocator
>&)
1154 /* XInitialization */
1155 void SAL_CALL
SAXEventKeeperImpl::initialize( const cssu::Sequence
< cssu::Any
>& aArguments
)
1157 OSL_ASSERT(aArguments
.getLength() == 1);
1159 aArguments
[0] >>= m_xXMLDocument
;
1160 m_xDocumentHandler
.set( m_xXMLDocument
, cssu::UNO_QUERY
);
1161 m_xCompressedDocumentHandler
.set( m_xXMLDocument
, cssu::UNO_QUERY
);
1163 m_pRootBufferNode
= new BufferNode(m_xXMLDocument
->getCurrentElement());
1164 m_pCurrentBufferNode
= m_pRootBufferNode
;
1167 OUString
SAXEventKeeperImpl_getImplementationName ()
1169 return OUString ( IMPLEMENTATION_NAME
);
1172 cssu::Sequence
< OUString
> SAL_CALL
SAXEventKeeperImpl_getSupportedServiceNames( )
1174 cssu::Sequence
<OUString
> aRet
{ "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
1179 OUString SAL_CALL
SAXEventKeeperImpl::getImplementationName( )
1181 return SAXEventKeeperImpl_getImplementationName();
1184 sal_Bool SAL_CALL
SAXEventKeeperImpl::supportsService( const OUString
& rServiceName
)
1186 return cppu::supportsService(this, rServiceName
);
1189 cssu::Sequence
< OUString
> SAL_CALL
SAXEventKeeperImpl::getSupportedServiceNames( )
1191 return SAXEventKeeperImpl_getSupportedServiceNames();
1194 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */