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/xml/sax/XDocumentHandler.hpp>
26 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
27 #include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
28 #include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <osl/diagnose.h>
31 #include <rtl/ustrbuf.hxx>
35 SAXEventKeeperImpl::SAXEventKeeperImpl( )
36 :m_pCurrentBufferNode(nullptr),
37 m_nNextElementMarkId(1),
38 m_pNewBlocker(nullptr),
39 m_pCurrentBlockingBufferNode(nullptr),
40 m_bIsReleasing(false),
41 m_bIsForwarding(false)
43 m_vElementMarkBuffers
.reserve(2);
44 m_vNewElementCollectors
.reserve(2);
45 m_vReleasedElementMarkBuffers
.reserve(2);
48 SAXEventKeeperImpl::~SAXEventKeeperImpl()
51 * delete the BufferNode tree
53 m_pRootBufferNode
.reset();
55 m_pCurrentBufferNode
= m_pCurrentBlockingBufferNode
= nullptr;
58 * delete all unfreed ElementMarks
60 m_vNewElementCollectors
.clear();
61 m_pNewBlocker
= nullptr;
64 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode
* pBufferNode
)
65 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
68 * setCurrentBufferNode -- set a new active BufferNode.
71 * setCurrentBufferNode( pBufferNode );
74 * connects this BufferNode into the BufferNode tree as a child of the
75 * current active BufferNode. Then makes this BufferNode as the current
77 * If the previous active BufferNode points to the root
78 * BufferNode, which means that no buffering operation was proceeding,
79 * then notifies the status change listener that buffering operation
83 * pBufferNode - a BufferNode which will be the new active BufferNode
84 ******************************************************************************/
86 if (pBufferNode
== m_pCurrentBufferNode
)
89 if ( m_pCurrentBufferNode
== m_pRootBufferNode
.get() &&
90 m_xSAXEventKeeperStatusChangeListener
.is())
92 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(true);
95 if (pBufferNode
->getParent() == nullptr)
97 m_pCurrentBufferNode
->addChild(std::unique_ptr
<BufferNode
>(pBufferNode
));
98 pBufferNode
->setParent(m_pCurrentBufferNode
);
101 m_pCurrentBufferNode
= pBufferNode
;
104 BufferNode
* SAXEventKeeperImpl::addNewElementMarkBuffers()
105 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
108 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
111 * pBufferNode = addNewElementMarkBuffers( );
114 * if there are new ElementCollector or new Blocker to be added, then
115 * connect all of them with the current BufferNode. In case of the
116 * current BufferNode doesn't exist, creates one.
117 * Clears up the new ElementCollector list and the new Blocker pointer.
120 * pBufferNode - the BufferNode that has been connected with both new
121 * ElementCollectors and new Blocker.
122 ******************************************************************************/
124 BufferNode
* pBufferNode
= nullptr;
126 if (m_pNewBlocker
|| !m_vNewElementCollectors
.empty() )
129 * When the current BufferNode is right pointing to the current
130 * working element in the XMLDocumentWrapper component, then
131 * no new BufferNode is needed to create.
132 * This situation can only happen in the "Forwarding" mode.
134 if ( (m_pCurrentBufferNode
!= nullptr) &&
135 (m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement())))
137 pBufferNode
= m_pCurrentBufferNode
;
141 pBufferNode
= new BufferNode(m_xXMLDocument
->getCurrentElement());
144 if (m_pNewBlocker
!= nullptr)
146 pBufferNode
->setBlocker(m_pNewBlocker
);
149 * If no blocking before, then notify the status change listener that
150 * the SAXEventKeeper has entered "blocking" status, during which, no
151 * SAX events will be forwarded to the next document handler.
153 if (m_pCurrentBlockingBufferNode
== nullptr)
155 m_pCurrentBlockingBufferNode
= pBufferNode
;
157 if (m_xSAXEventKeeperStatusChangeListener
.is())
159 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(true);
163 m_pNewBlocker
= nullptr;
166 for( const auto& i
: m_vNewElementCollectors
)
168 pBufferNode
->addElementCollector(i
);
170 m_vNewElementCollectors
.clear();
176 ElementMark
* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId
) const
177 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
180 * findElementMarkBuffer -- finds an ElementMark.
183 * pElementMark = findElementMarkBuffer( nId );
186 * searches an ElementMark with the particular Id in the ElementMark
190 * nId - the Id of the ElementMark to be searched.
193 * pElementMark - the ElementMark with the particular Id, or NULL when
195 ******************************************************************************/
197 ElementMark
* pElementMark
= nullptr;
199 for( auto&& ii
: m_vElementMarkBuffers
)
201 if ( nId
== ii
->getBufferId())
203 pElementMark
= const_cast<ElementMark
*>(ii
.get());
211 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId
)
212 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
215 * removeElementMarkBuffer -- removes an ElementMark
218 * removeElementMarkBuffer( nId );
221 * removes an ElementMark with the particular Id in the ElementMark list.
224 * nId - the Id of the ElementMark to be removed.
225 ******************************************************************************/
227 auto ii
= std::find_if(m_vElementMarkBuffers
.begin(), m_vElementMarkBuffers
.end(),
228 [nId
](std::unique_ptr
<const ElementMark
>& rElementMark
) { return nId
== rElementMark
->getBufferId(); }
230 if (ii
== m_vElementMarkBuffers
.end())
234 * checks whether this ElementMark still in the new ElementCollect array
236 auto jj
= std::find_if(m_vNewElementCollectors
.begin(), m_vNewElementCollectors
.end(),
237 [&ii
](const ElementCollector
* pElementCollector
) { return ii
->get() == pElementCollector
; }
239 if (jj
!= m_vNewElementCollectors
.end())
240 m_vNewElementCollectors
.erase(jj
);
243 * checks whether this ElementMark is the new Blocker
245 if (ii
->get() == m_pNewBlocker
)
247 m_pNewBlocker
= nullptr;
250 m_vElementMarkBuffers
.erase( ii
);
253 OUString
SAXEventKeeperImpl::printBufferNode(
254 BufferNode
const * pBufferNode
, sal_Int32 nIndent
) const
255 /****** SAXEventKeeperImpl/printBufferNode ***********************************
258 * printBufferNode -- retrieves the information of a BufferNode and its
262 * info = printBufferNode( pBufferNode, nIndent );
265 * all retrieved information includes:
266 * 1. whether it is the current BufferNode;
267 * 2. whether it is the current blocking BufferNode;
268 * 3. the name of the parent element;
269 * 4. the name of this element;
270 * 5. all ElementCollectors working on this BufferNode;
271 * 6. the Blocker working on this BufferNode;
272 * 7. all child BufferNodes' information.
275 * pBufferNode - the BufferNode from where information will be retrieved.
276 * nIndent - how many space characters prefixed before the output
280 * info - the information string
281 ******************************************************************************/
285 for ( int i
=0; i
<nIndent
; ++i
)
290 if (pBufferNode
== m_pCurrentBufferNode
)
295 if (pBufferNode
== m_pCurrentBlockingBufferNode
)
300 rc
.append(" " + m_xXMLDocument
->getNodeName(pBufferNode
->getXMLElement()));
302 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
303 if (pParent
!= nullptr)
305 rc
.append("[" + m_xXMLDocument
->getNodeName(pParent
->getXMLElement()) + "]");
308 rc
.append(":EC=" + pBufferNode
->printChildren() + " BR=");
310 ElementMark
* pBlocker
= pBufferNode
->getBlocker();
311 if (pBlocker
!= nullptr)
313 rc
.append( OUString::number(pBlocker
->getBufferId()) +
314 "(SecId=" + OUString::number( pBlocker
->getSecurityId() ) + ") ");
318 std::vector
< std::unique_ptr
<BufferNode
> > const & vChildren
= pBufferNode
->getChildren();
319 for( const auto& jj
: vChildren
)
321 rc
.append(printBufferNode(jj
.get(), nIndent
+4));
324 return rc
.makeStringAndClear();
327 css::uno::Sequence
< css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> >
328 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode
const * pBufferNode
)
329 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
332 * collectChildWorkingElement -- collects a BufferNode's all child
336 * list = collectChildWorkingElement( pBufferNode );
339 * pBufferNode - the BufferNode whose child Elements will be collected.
342 * list - the child Elements list.
343 ******************************************************************************/
345 std::vector
< std::unique_ptr
<BufferNode
> > const & vChildren
= pBufferNode
->getChildren();
347 css::uno::Sequence
< css::uno::Reference
<
348 css::xml::wrapper::XXMLElementWrapper
> > aChildrenCollection ( vChildren
.size());
350 std::transform(vChildren
.begin(), vChildren
.end(), aChildrenCollection
.getArray(),
351 [](const auto& i
) { return i
->getXMLElement(); });
353 return aChildrenCollection
;
356 void SAXEventKeeperImpl::smashBufferNode(
357 BufferNode
* pBufferNode
, bool bClearRoot
) const
358 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
361 * smashBufferNode -- removes a BufferNode along with its working
365 * smashBufferNode( pBufferNode, bClearRoot );
368 * removes the BufferNode's working element from the DOM document, while
369 * reserves all ancestor paths for its child BufferNodes.
370 * when any of the BufferNode's ancestor element is useless, removes it
372 * removes the BufferNode from the BufferNode tree.
375 * pBufferNode - the BufferNode to be removed
376 * bClearRoot - whether the root element also needs to be cleared up.
379 * when removing a Blocker's BufferNode, the bClearRoot flag should be
380 * true. Because a Blocker can buffer many SAX events which are not used
381 * by any other ElementCollector or Blocker.
382 * When the bClearRoot is set to true, the root BufferNode will be first
383 * cleared, with a stop flag setting at the next Blocking BufferNode. This
384 * operation can delete all useless buffered SAX events which are only
385 * needed by the Blocker to be deleted.
386 ******************************************************************************/
388 if (pBufferNode
->hasAnything())
391 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
394 * delete the XML data
396 if (pParent
== m_pRootBufferNode
.get())
398 bool bIsNotBlocking
= (m_pCurrentBlockingBufferNode
== nullptr);
399 bool bIsBlockInside
= false;
400 bool bIsBlockingAfterward
= false;
403 * If this is a blocker, then remove any out-element data
404 * which caused by blocking. The removal process will stop
405 * at the next blocker to avoid removing any useful data.
409 css::uno::Sequence
< css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> >
410 aChildElements
= collectChildWorkingElement(m_pRootBufferNode
.get());
413 * the clearUselessData only clearup the content in the
414 * node, not the node itself.
416 m_xXMLDocument
->clearUselessData(m_pRootBufferNode
->getXMLElement(),
418 bIsNotBlocking
?nullptr:
419 (m_pCurrentBlockingBufferNode
->getXMLElement()));
422 * remove the node if it is empty, then if its parent is also
423 * empty, remove it, then if the next parent is also empty,
424 * remove it,..., until parent become null.
426 m_xXMLDocument
->collapse( m_pRootBufferNode
->getXMLElement() );
430 * if blocking, check the relationship between this BufferNode and
431 * the current blocking BufferNode.
433 if ( !bIsNotBlocking
)
436 * the current blocking BufferNode is a descendant of this BufferNode.
438 bIsBlockInside
= (nullptr != pBufferNode
->isAncestor(m_pCurrentBlockingBufferNode
));
441 * the current blocking BufferNode locates behind this BufferNode in tree
444 bIsBlockingAfterward
= pBufferNode
->isPrevious(m_pCurrentBlockingBufferNode
);
448 * this BufferNode's working element needs to be deleted only when
449 * 1. there is no blocking, or
450 * 2. the current blocking BufferNode is a descendant of this BufferNode,
451 * (then in the BufferNode's working element, the useless data before the blocking
452 * element should be deleted.) or
453 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
454 * (then the useless data between the blocking element and the working element
455 * should be deleted.).
456 * Otherwise, this working element should not be deleted.
458 if ( bIsNotBlocking
|| bIsBlockInside
|| bIsBlockingAfterward
)
460 css::uno::Sequence
< css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> >
461 aChildElements
= collectChildWorkingElement(pBufferNode
);
464 * the clearUselessData only clearup the content in the
465 * node, not the node itself.
467 m_xXMLDocument
->clearUselessData(pBufferNode
->getXMLElement(),
469 bIsBlockInside
?(m_pCurrentBlockingBufferNode
->getXMLElement()):
473 * remove the node if it is empty, then if its parent is also
474 * empty, remove it, then if the next parent is also empty,
475 * remove it,..., until parent become null.
477 m_xXMLDocument
->collapse( pBufferNode
->getXMLElement() );
481 sal_Int32 nIndex
= pParent
->indexOfChild(pBufferNode
);
483 std::vector
< std::unique_ptr
<BufferNode
> > vChildren
= pBufferNode
->releaseChildren();
484 pParent
->removeChild(pBufferNode
); // delete buffernode
486 for( auto& i
: vChildren
)
488 i
->setParent(pParent
);
489 pParent
->addChild(std::move(i
), nIndex
);
494 BufferNode
* SAXEventKeeperImpl::findNextBlockingBufferNode(
495 BufferNode
* pStartBufferNode
)
496 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
499 * findNextBlockingBufferNode -- finds the next blocking BufferNode
500 * behind the particular BufferNode.
503 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
506 * pStartBufferNode - the BufferNode from where to search the next
507 * blocking BufferNode.
510 * pBufferNode - the next blocking BufferNode, or NULL if no such
512 ******************************************************************************/
514 BufferNode
* pNext
= nullptr;
516 if (pStartBufferNode
!= nullptr)
518 pNext
= pStartBufferNode
;
520 while (nullptr != (pNext
= const_cast<BufferNode
*>(pNext
->getNextNodeByTreeOrder())))
522 if (pNext
->getBlocker() != nullptr)
532 void SAXEventKeeperImpl::diffuse(BufferNode
* pBufferNode
)
533 /****** SAXEventKeeperImpl/diffuse *******************************************
536 * diffuse -- diffuse the notification.
539 * diffuse( pBufferNode );
542 * diffuse the collecting completion notification from the specific
543 * BufferNode along its parent link, until an ancestor which is not
544 * completely received is met.
547 * pBufferNode - the BufferNode from which the notification will be
549 ******************************************************************************/
551 BufferNode
* pParent
= pBufferNode
;
553 while(pParent
->isAllReceived())
555 pParent
->elementCollectorNotify();
556 pParent
= const_cast<BufferNode
*>(pParent
->getParent());
560 void SAXEventKeeperImpl::releaseElementMarkBuffer()
561 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
564 * releaseElementMarkBuffer -- releases useless ElementMarks
567 * releaseElementMarkBuffer( );
570 * releases each ElementMark in the releasing list
571 * m_vReleasedElementMarkBuffers.
572 * The operation differs between an ElementCollector and a Blocker.
573 ******************************************************************************/
575 m_bIsReleasing
= true;
576 while (!m_vReleasedElementMarkBuffers
.empty())
578 auto pId
= m_vReleasedElementMarkBuffers
.begin();
579 sal_Int32 nId
= *pId
;
580 m_vReleasedElementMarkBuffers
.erase( pId
);
582 ElementMark
* pElementMark
= findElementMarkBuffer(nId
);
584 if (pElementMark
!= nullptr)
586 if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR
587 == pElementMark
->getType())
592 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(pElementMark
);
594 css::xml::crypto::sax::ElementMarkPriority nPriority
= pElementCollector
->getPriority();
596 * Delete the EC from the buffer node.
598 BufferNode
* pBufferNode
= pElementCollector
->getBufferNode();
599 pBufferNode
->removeElementCollector(pElementCollector
);
601 if ( nPriority
== css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY
)
603 pBufferNode
->notifyBranch();
607 * delete the ElementMark
609 pElementCollector
= nullptr;
610 pElementMark
= nullptr;
611 removeElementMarkBuffer(nId
);
614 * delete the BufferNode
616 diffuse(pBufferNode
);
617 smashBufferNode(pBufferNode
, false);
625 * Delete the TH from the buffer node.
627 BufferNode
*pBufferNode
= pElementMark
->getBufferNode();
629 pBufferNode
->setBlocker(nullptr);
632 * If there is a following handler and no blocking now, then
635 if (m_pCurrentBlockingBufferNode
== pBufferNode
)
638 * Before forwarding, the next blocking point needs to be
641 m_pCurrentBlockingBufferNode
= findNextBlockingBufferNode(pBufferNode
);
644 * Forward the blocked events between these two STHs.
646 if (m_xNextHandler
.is())
648 BufferNode
* pTempCurrentBufferNode
= m_pCurrentBufferNode
;
649 BufferNode
* pTempCurrentBlockingBufferNode
= m_pCurrentBlockingBufferNode
;
651 m_pCurrentBufferNode
= pBufferNode
;
653 m_pCurrentBlockingBufferNode
= nullptr;
655 m_bIsForwarding
= true;
657 m_xXMLDocument
->generateSAXEvents(
660 pBufferNode
->getXMLElement(),
661 (pTempCurrentBlockingBufferNode
== nullptr)?nullptr:(pTempCurrentBlockingBufferNode
->getXMLElement()));
663 m_bIsForwarding
= false;
665 m_pCurrentBufferNode
= pTempCurrentBufferNode
;
666 if (m_pCurrentBlockingBufferNode
== nullptr)
668 m_pCurrentBlockingBufferNode
= pTempCurrentBlockingBufferNode
;
672 if (m_pCurrentBlockingBufferNode
== nullptr &&
673 m_xSAXEventKeeperStatusChangeListener
.is())
675 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(false);
680 * delete the ElementMark
682 pElementMark
= nullptr;
683 removeElementMarkBuffer(nId
);
686 * delete the BufferNode
688 diffuse(pBufferNode
);
689 smashBufferNode(pBufferNode
, true);
694 m_bIsReleasing
= false;
696 if (!m_pRootBufferNode
->hasAnything() &&
697 !m_pRootBufferNode
->hasChildren() &&
698 m_xSAXEventKeeperStatusChangeListener
.is())
700 m_xSAXEventKeeperStatusChangeListener
->bufferStatusChanged(true);
704 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId
)
705 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
708 * markElementMarkBuffer -- marks an ElementMark to be released
711 * markElementMarkBuffer( nId );
714 * puts the ElementMark with the particular Id into the releasing list,
715 * checks whether the releasing process is running, if not then launch
719 * nId - the Id of the ElementMark which will be released
720 ******************************************************************************/
722 m_vReleasedElementMarkBuffers
.push_back( nId
);
723 if ( !m_bIsReleasing
)
725 releaseElementMarkBuffer();
729 sal_Int32
SAXEventKeeperImpl::createElementCollector(
730 css::xml::crypto::sax::ElementMarkPriority nPriority
,
732 const css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
>& xReferenceResolvedListener
)
733 /****** SAXEventKeeperImpl/createElementCollector ****************************
736 * createElementCollector -- creates a new ElementCollector on the
740 * nId = createElementCollector( nSecurityId, nPriority,
742 * xReferenceResolvedListener );
745 * allocs a new Id, then create an ElementCollector with this Id value.
746 * Add the new created ElementCollector to the new ElementCollecotor list.
749 * nPriority - the priority of the new ElementCollector
750 * bModifyElement -whether this BufferNode will modify the content of
751 * the corresponding element it works on
752 * xReferenceResolvedListener - the listener for the new ElementCollector.
755 * nId - the Id of the new ElementCollector
756 ******************************************************************************/
758 sal_Int32 nId
= m_nNextElementMarkId
;
759 m_nNextElementMarkId
++;
761 ElementCollector
* pElementCollector
762 = new ElementCollector(
766 xReferenceResolvedListener
);
768 m_vElementMarkBuffers
.push_back(
769 std::unique_ptr
<const ElementMark
>(pElementCollector
));
772 * All the new EC to initial EC array.
774 m_vNewElementCollectors
.push_back( pElementCollector
);
780 sal_Int32
SAXEventKeeperImpl::createBlocker()
781 /****** SAXEventKeeperImpl/createBlocker *************************************
784 * createBlocker -- creates a new Blocker on the incoming element.
787 * nId = createBlocker( nSecurityId );
790 * nId - the Id of the new Blocker
791 ******************************************************************************/
793 sal_Int32 nId
= m_nNextElementMarkId
;
794 m_nNextElementMarkId
++;
796 OSL_ASSERT(m_pNewBlocker
== nullptr);
798 m_pNewBlocker
= new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
, nId
);
799 m_vElementMarkBuffers
.push_back(
800 std::unique_ptr
<const ElementMark
>(m_pNewBlocker
));
805 /* XSAXEventKeeper */
806 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addElementCollector( )
808 return createElementCollector(
809 css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY
,
814 void SAL_CALL
SAXEventKeeperImpl::removeElementCollector( sal_Int32 id
)
816 markElementMarkBuffer(id
);
819 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addBlocker( )
821 return createBlocker();
824 void SAL_CALL
SAXEventKeeperImpl::removeBlocker( sal_Int32 id
)
826 markElementMarkBuffer(id
);
829 sal_Bool SAL_CALL
SAXEventKeeperImpl::isBlocking( )
831 return (m_pCurrentBlockingBufferNode
!= nullptr);
834 css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> SAL_CALL
835 SAXEventKeeperImpl::getElement( sal_Int32 id
)
837 css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> rc
;
839 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
840 if (pElementMark
!= nullptr)
842 rc
= pElementMark
->getBufferNode()->getXMLElement();
848 void SAL_CALL
SAXEventKeeperImpl::setElement(
850 const css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
>& aElement
)
854 m_xXMLDocument
->rebuildIDLink(aElement
);
856 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
858 if (pElementMark
!= nullptr)
860 BufferNode
* pBufferNode
= pElementMark
->getBufferNode();
861 if (pBufferNode
!= nullptr)
863 const bool bIsCurrent
= m_xXMLDocument
->isCurrent(pBufferNode
->getXMLElement());
864 pBufferNode
->setXMLElement(aElement
);
868 m_xXMLDocument
->setCurrentElement(aElement
);
875 removeElementCollector( id
);
879 css::uno::Reference
< css::xml::sax::XDocumentHandler
> SAL_CALL
SAXEventKeeperImpl::setNextHandler(
880 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xNewHandler
)
882 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xOldHandler
= m_xNextHandler
;
884 m_xNextHandler
= xNewHandler
;
888 OUString SAL_CALL
SAXEventKeeperImpl::printBufferNodeTree()
890 OUString rc
= "ElementMarkBuffers: size = "
891 + OUString::number(m_vElementMarkBuffers
.size())
892 + "\nCurrentBufferNode: "
893 + m_xXMLDocument
->getNodeName(m_pCurrentBufferNode
->getXMLElement())
894 + "\n" + printBufferNode(m_pRootBufferNode
.get(), 0);
899 css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> SAL_CALL
SAXEventKeeperImpl::getCurrentBlockingNode()
901 css::uno::Reference
< css::xml::wrapper::XXMLElementWrapper
> rc
;
903 if (m_pCurrentBlockingBufferNode
!= nullptr)
905 rc
= m_pCurrentBlockingBufferNode
->getXMLElement();
911 /* XSecuritySAXEventKeeper */
912 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addSecurityElementCollector(
913 css::xml::crypto::sax::ElementMarkPriority priority
,
914 sal_Bool modifyElement
)
916 return createElementCollector(
922 void SAL_CALL
SAXEventKeeperImpl::setSecurityId( sal_Int32 id
, sal_Int32 securityId
)
924 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
925 if (pElementMark
!= nullptr)
927 pElementMark
->setSecurityId(securityId
);
932 /* XReferenceResolvedBroadcaster */
933 void SAL_CALL
SAXEventKeeperImpl::addReferenceResolvedListener(
934 sal_Int32 referenceId
,
935 const css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
>& listener
)
937 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(findElementMarkBuffer(referenceId
));
938 if (pElementCollector
!= nullptr)
940 pElementCollector
->setReferenceResolvedListener(listener
);
944 void SAL_CALL
SAXEventKeeperImpl::removeReferenceResolvedListener(
945 sal_Int32
/*referenceId*/,
946 const css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
>&)
950 /* XSAXEventKeeperStatusChangeBroadcaster */
951 void SAL_CALL
SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
952 const css::uno::Reference
< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener
>& listener
)
954 m_xSAXEventKeeperStatusChangeListener
= listener
;
957 void SAL_CALL
SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
958 const css::uno::Reference
< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener
>&)
962 /* XDocumentHandler */
963 void SAL_CALL
SAXEventKeeperImpl::startDocument( )
965 if ( m_xNextHandler
.is())
967 m_xNextHandler
->startDocument();
971 void SAL_CALL
SAXEventKeeperImpl::endDocument( )
973 if ( m_xNextHandler
.is())
975 m_xNextHandler
->endDocument();
979 void SAL_CALL
SAXEventKeeperImpl::startElement(
980 const OUString
& aName
,
981 const css::uno::Reference
< css::xml::sax::XAttributeList
>& xAttribs
)
984 * If there is a following handler and no blocking now, then
987 if ((m_pCurrentBlockingBufferNode
== nullptr) &&
988 (m_xNextHandler
.is()) &&
989 (!m_bIsForwarding
) &&
990 (m_pNewBlocker
== nullptr))
992 m_xNextHandler
->startElement(aName
, xAttribs
);
995 * If not forwarding, buffer this startElement.
997 if (!m_bIsForwarding
)
999 sal_Int32 nLength
= xAttribs
->getLength();
1000 css::uno::Sequence
< css::xml::csax::XMLAttribute
> aAttributes (nLength
);
1001 auto aAttributesRange
= asNonConstRange(aAttributes
);
1003 for ( int i
= 0; i
<nLength
; ++i
)
1005 aAttributesRange
[i
].sName
= xAttribs
->getNameByIndex(static_cast<short>(i
));
1006 aAttributesRange
[i
].sValue
=xAttribs
->getValueByIndex(static_cast<short>(i
));
1009 m_xCompressedDocumentHandler
->compressedStartElement(aName
, aAttributes
);
1012 BufferNode
* pBufferNode
= addNewElementMarkBuffers();
1013 if (pBufferNode
!= nullptr)
1015 setCurrentBufferNode(pBufferNode
);
1019 void SAL_CALL
SAXEventKeeperImpl::endElement( const OUString
& aName
)
1021 const bool bIsCurrent
= m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement());
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()) &&
1031 m_xNextHandler
->endElement(aName
);
1034 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1035 (m_pCurrentBufferNode
!= m_pRootBufferNode
.get()) ||
1036 (!m_xXMLDocument
->isCurrentElementEmpty()))
1038 if (!m_bIsForwarding
)
1040 m_xCompressedDocumentHandler
->compressedEndElement(aName
);
1044 * If the current buffer node has not notified yet, and
1045 * the current buffer node is waiting for the current element,
1046 * then let it notify.
1048 if (bIsCurrent
&& (m_pCurrentBufferNode
!= m_pRootBufferNode
.get()))
1050 BufferNode
* pOldCurrentBufferNode
= m_pCurrentBufferNode
;
1051 m_pCurrentBufferNode
= const_cast<BufferNode
*>(m_pCurrentBufferNode
->getParent());
1053 pOldCurrentBufferNode
->setReceivedAll();
1055 if ((m_pCurrentBufferNode
== m_pRootBufferNode
.get()) &&
1056 m_xSAXEventKeeperStatusChangeListener
.is())
1058 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(false);
1064 if (!m_bIsForwarding
)
1066 m_xXMLDocument
->removeCurrentElement();
1071 void SAL_CALL
SAXEventKeeperImpl::characters( const OUString
& aChars
)
1073 if (m_bIsForwarding
)
1076 if ((m_pCurrentBlockingBufferNode
== nullptr) && m_xNextHandler
.is())
1078 m_xNextHandler
->characters(aChars
);
1081 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1082 (m_pCurrentBufferNode
!= m_pRootBufferNode
.get()))
1084 m_xCompressedDocumentHandler
->compressedCharacters(aChars
);
1088 void SAL_CALL
SAXEventKeeperImpl::ignorableWhitespace( const OUString
& aWhitespaces
)
1090 characters( aWhitespaces
);
1093 void SAL_CALL
SAXEventKeeperImpl::processingInstruction(
1094 const OUString
& aTarget
, const OUString
& aData
)
1096 if (m_bIsForwarding
)
1099 if ((m_pCurrentBlockingBufferNode
== nullptr) && m_xNextHandler
.is())
1101 m_xNextHandler
->processingInstruction(aTarget
, aData
);
1104 if ((m_pCurrentBlockingBufferNode
!= nullptr) ||
1105 (m_pCurrentBufferNode
!= m_pRootBufferNode
.get()))
1107 m_xCompressedDocumentHandler
->compressedProcessingInstruction(aTarget
, aData
);
1111 void SAL_CALL
SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference
< css::xml::sax::XLocator
>&)
1115 /* XInitialization */
1116 void SAL_CALL
SAXEventKeeperImpl::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
1118 OSL_ASSERT(aArguments
.getLength() == 1);
1120 aArguments
[0] >>= m_xXMLDocument
;
1121 m_xDocumentHandler
.set( m_xXMLDocument
, css::uno::UNO_QUERY
);
1122 m_xCompressedDocumentHandler
.set( m_xXMLDocument
, css::uno::UNO_QUERY
);
1124 m_pRootBufferNode
.reset( new BufferNode(m_xXMLDocument
->getCurrentElement()) );
1125 m_pCurrentBufferNode
= m_pRootBufferNode
.get();
1128 OUString
SAXEventKeeperImpl_getImplementationName ()
1130 return u
"com.sun.star.xml.security.framework.SAXEventKeeperImpl"_ustr
;
1133 css::uno::Sequence
< OUString
> SAXEventKeeperImpl_getSupportedServiceNames( )
1135 return { u
"com.sun.star.xml.crypto.sax.SAXEventKeeper"_ustr
};
1139 OUString SAL_CALL
SAXEventKeeperImpl::getImplementationName( )
1141 return SAXEventKeeperImpl_getImplementationName();
1144 sal_Bool SAL_CALL
SAXEventKeeperImpl::supportsService( const OUString
& rServiceName
)
1146 return cppu::supportsService(this, rServiceName
);
1149 css::uno::Sequence
< OUString
> SAL_CALL
SAXEventKeeperImpl::getSupportedServiceNames( )
1151 return SAXEventKeeperImpl_getSupportedServiceNames();
1154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */