Bump version to 6.0-36
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blobc1855ecd31ca0bf4700ed20b37bfa4cdf695ec1f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 ******************************
77 * NAME
78 * setCurrentBufferNode -- set a new active BufferNode.
80 * SYNOPSIS
81 * setCurrentBufferNode( pBufferNode );
83 * FUNCTION
84 * connects this BufferNode into the BufferNode tree as a child of the
85 * current active BufferNode. Then makes this BufferNode as the current
86 * active BufferNode.
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
90 * will begin at once.
92 * INPUTS
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 **************************
117 * NAME
118 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
120 * SYNOPSIS
121 * pBufferNode = addNewElementMarkBuffers( );
123 * FUNCTION
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.
129 * RESULT
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;
149 else
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();
188 return pBufferNode;
191 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
192 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
194 * NAME
195 * findElementMarkBuffer -- finds an ElementMark.
197 * SYNOPSIS
198 * pElementMark = findElementMarkBuffer( nId );
200 * FUNCTION
201 * searches an ElementMark with the particular Id in the ElementMark
202 * list.
204 * INPUTS
205 * nId - the Id of the ElementMark to be searched.
207 * RESULT
208 * pElementMark - the ElementMark with the particular Id, or NULL when
209 * no such Id exists.
210 ******************************************************************************/
212 ElementMark* pElementMark = nullptr;
214 for( auto&& ii : m_vElementMarkBuffers )
216 if ( nId == ii->getBufferId())
218 pElementMark = const_cast<ElementMark*>(ii.get());
219 break;
223 return pElementMark;
226 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
227 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
229 * NAME
230 * removeElementMarkBuffer -- removes an ElementMark
232 * SYNOPSIS
233 * removeElementMarkBuffer( nId );
235 * FUNCTION
236 * removes an ElementMark with the particular Id in the ElementMark list.
238 * INPUTS
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);
256 break;
261 * checks whether this ElementMark is the new Blocker
263 if (ii->get() == m_pNewBlocker)
265 m_pNewBlocker = nullptr;
268 m_vElementMarkBuffers.erase( ii );
269 break;
274 OUString SAXEventKeeperImpl::printBufferNode(
275 BufferNode const * pBufferNode, sal_Int32 nIndent) const
276 /****** SAXEventKeeperImpl/printBufferNode ***********************************
278 * NAME
279 * printBufferNode -- retrieves the information of a BufferNode and its
280 * branch.
282 * SYNOPSIS
283 * info = printBufferNode( pBufferNode, nIndent );
285 * FUNCTION
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.
295 * INPUTS
296 * pBufferNode - the BufferNode from where information will be retrieved.
297 * nIndent - how many space characters prefixed before the output
298 * message.
300 * RESULT
301 * info - the information string
302 ******************************************************************************/
304 OUString rc;
306 for ( int i=0; i<nIndent; ++i )
308 rc += " ";
311 if (pBufferNode == m_pCurrentBufferNode)
313 rc += "[%]";
316 if (pBufferNode == m_pCurrentBlockingBufferNode)
318 rc += "[B]";
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() ) + ") ";
337 rc += "\n";
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);
346 delete vChildren;
348 return rc;
351 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
352 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode const * pBufferNode)
353 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
355 * NAME
356 * collectChildWorkingElement -- collects a BufferNode's all child
357 * Elements.
359 * SYNOPSIS
360 * list = collectChildWorkingElement( pBufferNode );
362 * INPUTS
363 * pBufferNode - the BufferNode whose child Elements will be collected.
365 * RESULT
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();
379 nIndex++;
382 delete vChildren;
384 return aChildrenCollection;
387 void SAXEventKeeperImpl::smashBufferNode(
388 BufferNode* pBufferNode, bool bClearRoot) const
389 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
391 * NAME
392 * smashBufferNode -- removes a BufferNode along with its working
393 * element.
395 * SYNOPSIS
396 * smashBufferNode( pBufferNode, bClearRoot );
398 * FUNCTION
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
402 * too.
403 * removes the BufferNode from the BufferNode tree.
405 * INPUTS
406 * pBufferNode - the BufferNode to be removed
407 * bClearRoot - whether the root element also needs to be cleared up.
409 * NOTES
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.
437 if (bClearRoot)
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(),
447 aChildElements,
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
472 * order.
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(),
498 aChildElements,
499 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
500 (nullptr));
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);
522 nIndex++;
525 delete vChildren;
528 * delete the BufferNode
530 delete pBufferNode;
534 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
535 BufferNode* pStartBufferNode)
536 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
538 * NAME
539 * findNextBlockingBufferNode -- finds the next blocking BufferNode
540 * behind the particular BufferNode.
542 * SYNOPSIS
543 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
545 * INPUTS
546 * pStartBufferNode - the BufferNode from where to search the next
547 * blocking BufferNode.
549 * RESULT
550 * pBufferNode - the next blocking BufferNode, or NULL if no such
551 * BufferNode exists.
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)
564 break;
569 return pNext;
572 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode)
573 /****** SAXEventKeeperImpl/diffuse *******************************************
575 * NAME
576 * diffuse -- diffuse the notification.
578 * SYNOPSIS
579 * diffuse( pBufferNode );
581 * FUNCTION
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.
586 * INPUTS
587 * pBufferNode - the BufferNode from which the notification will be
588 * diffused.
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 **************************
603 * NAME
604 * releaseElementMarkBuffer -- releases useless ElementMarks
606 * SYNOPSIS
607 * releaseElementMarkBuffer( );
609 * FUNCTION
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())
629 * it is a EC
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);
659 else
661 * it is a Blocker
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
672 * forward this event
674 if (m_pCurrentBlockingBufferNode == pBufferNode)
677 * Before forwarding, the next blocking point needs to be
678 * found.
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(
696 m_xNextHandler,
697 this,
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 *****************************
745 * NAME
746 * markElementMarkBuffer -- marks an ElementMark to be released
748 * SYNOPSIS
749 * markElementMarkBuffer( nId );
751 * FUNCTION
752 * puts the ElementMark with the particular Id into the releasing list,
753 * checks whether the releasing process is running, if not then launch
754 * this process.
756 * INPUTS
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,
769 bool bModifyElement,
770 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
771 /****** SAXEventKeeperImpl/createElementCollector ****************************
773 * NAME
774 * createElementCollector -- creates a new ElementCollector on the
775 * incoming element.
777 * SYNOPSIS
778 * nId = createElementCollector( nSecurityId, nPriority,
779 * bModifyElement,
780 * xReferenceResolvedListener );
782 * FUNCTION
783 * allocs a new Id, then create an ElementCollector with this Id value.
784 * Add the new created ElementCollector to the new ElementCollecotor list.
786 * INPUTS
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.
792 * RESULT
793 * nId - the Id of the new ElementCollector
794 ******************************************************************************/
796 sal_Int32 nId = m_nNextElementMarkId;
797 m_nNextElementMarkId ++;
799 ElementCollector* pElementCollector
800 = new ElementCollector(
801 nId,
802 nPriority,
803 bModifyElement,
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 );
814 return nId;
818 sal_Int32 SAXEventKeeperImpl::createBlocker()
819 /****** SAXEventKeeperImpl/createBlocker *************************************
821 * NAME
822 * createBlocker -- creates a new Blocker on the incoming element.
824 * SYNOPSIS
825 * nId = createBlocker( nSecurityId );
827 * RESULT
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));
840 return nId;
843 /* XSAXEventKeeper */
844 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
846 return createElementCollector(
847 cssxc::sax::ElementMarkPriority_AFTERMODIFY,
848 false,
849 nullptr);
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();
883 return rc;
886 void SAL_CALL SAXEventKeeperImpl::setElement(
887 sal_Int32 id,
888 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
890 if (aElement.is())
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);
904 if (bIsCurrent)
906 m_xXMLDocument->setCurrentElement(aElement);
911 else
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;
923 return xOldHandler;
926 OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
928 OUString rc;
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);
936 return rc;
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();
948 return rc;
951 /* XSecuritySAXEventKeeper */
952 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
953 cssxc::sax::ElementMarkPriority priority,
954 sal_Bool modifyElement )
956 return createElementCollector(
957 priority,
958 modifyElement,
959 nullptr);
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()) &&
1068 (!m_bIsForwarding))
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);
1101 else
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" };
1175 return aRet;
1178 /* XServiceInfo */
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: */