nss: upgrade to release 3.73
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blobfee60ce925bde37fa1b030a6c88bf84038ec35f8
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/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>
33 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
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 ******************************
67 * NAME
68 * setCurrentBufferNode -- set a new active BufferNode.
70 * SYNOPSIS
71 * setCurrentBufferNode( pBufferNode );
73 * FUNCTION
74 * connects this BufferNode into the BufferNode tree as a child of the
75 * current active BufferNode. Then makes this BufferNode as the current
76 * active BufferNode.
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
80 * will begin at once.
82 * INPUTS
83 * pBufferNode - a BufferNode which will be the new active BufferNode
84 ******************************************************************************/
86 if (pBufferNode == m_pCurrentBufferNode)
87 return;
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 **************************
107 * NAME
108 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
110 * SYNOPSIS
111 * pBufferNode = addNewElementMarkBuffers( );
113 * FUNCTION
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.
119 * RESULT
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;
139 else
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();
173 return pBufferNode;
176 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
177 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
179 * NAME
180 * findElementMarkBuffer -- finds an ElementMark.
182 * SYNOPSIS
183 * pElementMark = findElementMarkBuffer( nId );
185 * FUNCTION
186 * searches an ElementMark with the particular Id in the ElementMark
187 * list.
189 * INPUTS
190 * nId - the Id of the ElementMark to be searched.
192 * RESULT
193 * pElementMark - the ElementMark with the particular Id, or NULL when
194 * no such Id exists.
195 ******************************************************************************/
197 ElementMark* pElementMark = nullptr;
199 for( auto&& ii : m_vElementMarkBuffers )
201 if ( nId == ii->getBufferId())
203 pElementMark = const_cast<ElementMark*>(ii.get());
204 break;
208 return pElementMark;
211 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
212 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
214 * NAME
215 * removeElementMarkBuffer -- removes an ElementMark
217 * SYNOPSIS
218 * removeElementMarkBuffer( nId );
220 * FUNCTION
221 * removes an ElementMark with the particular Id in the ElementMark list.
223 * INPUTS
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())
231 return;
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 ***********************************
257 * NAME
258 * printBufferNode -- retrieves the information of a BufferNode and its
259 * branch.
261 * SYNOPSIS
262 * info = printBufferNode( pBufferNode, nIndent );
264 * FUNCTION
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.
274 * INPUTS
275 * pBufferNode - the BufferNode from where information will be retrieved.
276 * nIndent - how many space characters prefixed before the output
277 * message.
279 * RESULT
280 * info - the information string
281 ******************************************************************************/
283 OUStringBuffer rc;
285 for ( int i=0; i<nIndent; ++i )
287 rc.append(" ");
290 if (pBufferNode == m_pCurrentBufferNode)
292 rc.append("[%]");
295 if (pBufferNode == m_pCurrentBlockingBufferNode)
297 rc.append("[B]");
300 rc.append(" ").append(m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()));
302 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
303 if (pParent != nullptr)
305 rc.append("[").append(m_xXMLDocument->getNodeName(pParent->getXMLElement())).append("]");
308 rc.append(":EC=").append(pBufferNode->printChildren()).append(" BR=");
310 ElementMark * pBlocker = pBufferNode->getBlocker();
311 if (pBlocker != nullptr)
313 rc.append(OUString::number( pBlocker->getBufferId() )).append("(SecId=")
314 .append(OUString::number( pBlocker->getSecurityId() )).append(") ");
316 rc.append("\n");
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 ************************
331 * NAME
332 * collectChildWorkingElement -- collects a BufferNode's all child
333 * Elements.
335 * SYNOPSIS
336 * list = collectChildWorkingElement( pBufferNode );
338 * INPUTS
339 * pBufferNode - the BufferNode whose child Elements will be collected.
341 * RESULT
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 sal_Int32 nIndex = 0;
351 for( const auto& i : vChildren )
353 aChildrenCollection[nIndex] = i->getXMLElement();
354 nIndex++;
357 return aChildrenCollection;
360 void SAXEventKeeperImpl::smashBufferNode(
361 BufferNode* pBufferNode, bool bClearRoot) const
362 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
364 * NAME
365 * smashBufferNode -- removes a BufferNode along with its working
366 * element.
368 * SYNOPSIS
369 * smashBufferNode( pBufferNode, bClearRoot );
371 * FUNCTION
372 * removes the BufferNode's working element from the DOM document, while
373 * reserves all ancestor paths for its child BufferNodes.
374 * when any of the BufferNode's ancestor element is useless, removes it
375 * too.
376 * removes the BufferNode from the BufferNode tree.
378 * INPUTS
379 * pBufferNode - the BufferNode to be removed
380 * bClearRoot - whether the root element also needs to be cleared up.
382 * NOTES
383 * when removing a Blocker's BufferNode, the bClearRoot flag should be
384 * true. Because a Blocker can buffer many SAX events which are not used
385 * by any other ElementCollector or Blocker.
386 * When the bClearRoot is set to true, the root BufferNode will be first
387 * cleared, with a stop flag setting at the next Blocking BufferNode. This
388 * operation can delete all useless buffered SAX events which are only
389 * needed by the Blocker to be deleted.
390 ******************************************************************************/
392 if (pBufferNode->hasAnything())
393 return;
395 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
398 * delete the XML data
400 if (pParent == m_pRootBufferNode.get())
402 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr);
403 bool bIsBlockInside = false;
404 bool bIsBlockingAfterward = false;
407 * If this is a blocker, then remove any out-element data
408 * which caused by blocking. The removal process will stop
409 * at the next blocker to avoid removing any useful data.
411 if (bClearRoot)
413 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
414 aChildElements = collectChildWorkingElement(m_pRootBufferNode.get());
417 * the clearUselessData only clearup the content in the
418 * node, not the node itself.
420 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
421 aChildElements,
422 bIsNotBlocking?nullptr:
423 (m_pCurrentBlockingBufferNode->getXMLElement()));
426 * remove the node if it is empty, then if its parent is also
427 * empty, remove it, then if the next parent is also empty,
428 * remove it,..., until parent become null.
430 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
434 * if blocking, check the relationship between this BufferNode and
435 * the current blocking BufferNode.
437 if ( !bIsNotBlocking )
440 * the current blocking BufferNode is a descendant of this BufferNode.
442 bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
445 * the current blocking BufferNode locates behind this BufferNode in tree
446 * order.
448 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
452 * this BufferNode's working element needs to be deleted only when
453 * 1. there is no blocking, or
454 * 2. the current blocking BufferNode is a descendant of this BufferNode,
455 * (then in the BufferNode's working element, the useless data before the blocking
456 * element should be deleted.) or
457 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
458 * (then the useless data between the blocking element and the working element
459 * should be deleted.).
460 * Otherwise, this working element should not be deleted.
462 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
464 css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
465 aChildElements = collectChildWorkingElement(pBufferNode);
468 * the clearUselessData only clearup the content in the
469 * node, not the node itself.
471 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
472 aChildElements,
473 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
474 nullptr);
477 * remove the node if it is empty, then if its parent is also
478 * empty, remove it, then if the next parent is also empty,
479 * remove it,..., until parent become null.
481 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
485 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
487 std::vector< std::unique_ptr<BufferNode> > vChildren = pBufferNode->releaseChildren();
488 pParent->removeChild(pBufferNode); // delete buffernode
490 for( auto& i : vChildren )
492 i->setParent(pParent);
493 pParent->addChild(std::move(i), nIndex);
494 nIndex++;
498 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
499 BufferNode* pStartBufferNode)
500 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
502 * NAME
503 * findNextBlockingBufferNode -- finds the next blocking BufferNode
504 * behind the particular BufferNode.
506 * SYNOPSIS
507 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
509 * INPUTS
510 * pStartBufferNode - the BufferNode from where to search the next
511 * blocking BufferNode.
513 * RESULT
514 * pBufferNode - the next blocking BufferNode, or NULL if no such
515 * BufferNode exists.
516 ******************************************************************************/
518 BufferNode* pNext = nullptr;
520 if (pStartBufferNode != nullptr)
522 pNext = pStartBufferNode;
524 while (nullptr != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder())))
526 if (pNext->getBlocker() != nullptr)
528 break;
533 return pNext;
536 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode)
537 /****** SAXEventKeeperImpl/diffuse *******************************************
539 * NAME
540 * diffuse -- diffuse the notification.
542 * SYNOPSIS
543 * diffuse( pBufferNode );
545 * FUNCTION
546 * diffuse the collecting completion notification from the specific
547 * BufferNode along its parent link, until an ancestor which is not
548 * completely received is met.
550 * INPUTS
551 * pBufferNode - the BufferNode from which the notification will be
552 * diffused.
553 ******************************************************************************/
555 BufferNode* pParent = pBufferNode;
557 while(pParent->isAllReceived())
559 pParent->elementCollectorNotify();
560 pParent = const_cast<BufferNode*>(pParent->getParent());
564 void SAXEventKeeperImpl::releaseElementMarkBuffer()
565 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
567 * NAME
568 * releaseElementMarkBuffer -- releases useless ElementMarks
570 * SYNOPSIS
571 * releaseElementMarkBuffer( );
573 * FUNCTION
574 * releases each ElementMark in the releasing list
575 * m_vReleasedElementMarkBuffers.
576 * The operation differs between an ElementCollector and a Blocker.
577 ******************************************************************************/
579 m_bIsReleasing = true;
580 while (!m_vReleasedElementMarkBuffers.empty())
582 auto pId = m_vReleasedElementMarkBuffers.begin();
583 sal_Int32 nId = *pId;
584 m_vReleasedElementMarkBuffers.erase( pId );
586 ElementMark* pElementMark = findElementMarkBuffer(nId);
588 if (pElementMark != nullptr)
590 if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR
591 == pElementMark->getType())
593 * it is a EC
596 ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark);
598 css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
600 * Delete the EC from the buffer node.
602 BufferNode* pBufferNode = pElementCollector->getBufferNode();
603 pBufferNode->removeElementCollector(pElementCollector);
605 if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY)
607 pBufferNode->notifyBranch();
611 * delete the ElementMark
613 pElementCollector = nullptr;
614 pElementMark = nullptr;
615 removeElementMarkBuffer(nId);
618 * delete the BufferNode
620 diffuse(pBufferNode);
621 smashBufferNode(pBufferNode, false);
623 else
625 * it is a Blocker
629 * Delete the TH from the buffer node.
631 BufferNode *pBufferNode = pElementMark->getBufferNode();
632 pBufferNode->setBlocker(nullptr);
635 * If there is a following handler and no blocking now, then
636 * forward this event
638 if (m_pCurrentBlockingBufferNode == pBufferNode)
641 * Before forwarding, the next blocking point needs to be
642 * found.
644 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
647 * Forward the blocked events between these two STHs.
649 if (m_xNextHandler.is())
651 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
652 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
654 m_pCurrentBufferNode = pBufferNode;
655 m_pCurrentBlockingBufferNode = nullptr;
657 m_bIsForwarding = true;
659 m_xXMLDocument->generateSAXEvents(
660 m_xNextHandler,
661 this,
662 pBufferNode->getXMLElement(),
663 (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement()));
665 m_bIsForwarding = false;
667 m_pCurrentBufferNode = pTempCurrentBufferNode;
668 if (m_pCurrentBlockingBufferNode == nullptr)
670 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
674 if (m_pCurrentBlockingBufferNode == nullptr &&
675 m_xSAXEventKeeperStatusChangeListener.is())
677 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false);
682 * delete the ElementMark
684 pElementMark = nullptr;
685 removeElementMarkBuffer(nId);
688 * delete the BufferNode
690 diffuse(pBufferNode);
691 smashBufferNode(pBufferNode, true);
696 m_bIsReleasing = false;
698 if (!m_pRootBufferNode->hasAnything() &&
699 !m_pRootBufferNode->hasChildren() &&
700 m_xSAXEventKeeperStatusChangeListener.is())
702 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true);
706 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
707 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
709 * NAME
710 * markElementMarkBuffer -- marks an ElementMark to be released
712 * SYNOPSIS
713 * markElementMarkBuffer( nId );
715 * FUNCTION
716 * puts the ElementMark with the particular Id into the releasing list,
717 * checks whether the releasing process is running, if not then launch
718 * this process.
720 * INPUTS
721 * nId - the Id of the ElementMark which will be released
722 ******************************************************************************/
724 m_vReleasedElementMarkBuffers.push_back( nId );
725 if ( !m_bIsReleasing )
727 releaseElementMarkBuffer();
731 sal_Int32 SAXEventKeeperImpl::createElementCollector(
732 css::xml::crypto::sax::ElementMarkPriority nPriority,
733 bool bModifyElement,
734 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
735 /****** SAXEventKeeperImpl/createElementCollector ****************************
737 * NAME
738 * createElementCollector -- creates a new ElementCollector on the
739 * incoming element.
741 * SYNOPSIS
742 * nId = createElementCollector( nSecurityId, nPriority,
743 * bModifyElement,
744 * xReferenceResolvedListener );
746 * FUNCTION
747 * allocs a new Id, then create an ElementCollector with this Id value.
748 * Add the new created ElementCollector to the new ElementCollecotor list.
750 * INPUTS
751 * nPriority - the priority of the new ElementCollector
752 * bModifyElement -whether this BufferNode will modify the content of
753 * the corresponding element it works on
754 * xReferenceResolvedListener - the listener for the new ElementCollector.
756 * RESULT
757 * nId - the Id of the new ElementCollector
758 ******************************************************************************/
760 sal_Int32 nId = m_nNextElementMarkId;
761 m_nNextElementMarkId ++;
763 ElementCollector* pElementCollector
764 = new ElementCollector(
765 nId,
766 nPriority,
767 bModifyElement,
768 xReferenceResolvedListener);
770 m_vElementMarkBuffers.push_back(
771 std::unique_ptr<const ElementMark>(pElementCollector));
774 * All the new EC to initial EC array.
776 m_vNewElementCollectors.push_back( pElementCollector );
778 return nId;
782 sal_Int32 SAXEventKeeperImpl::createBlocker()
783 /****** SAXEventKeeperImpl/createBlocker *************************************
785 * NAME
786 * createBlocker -- creates a new Blocker on the incoming element.
788 * SYNOPSIS
789 * nId = createBlocker( nSecurityId );
791 * RESULT
792 * nId - the Id of the new Blocker
793 ******************************************************************************/
795 sal_Int32 nId = m_nNextElementMarkId;
796 m_nNextElementMarkId ++;
798 OSL_ASSERT(m_pNewBlocker == nullptr);
800 m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId);
801 m_vElementMarkBuffers.push_back(
802 std::unique_ptr<const ElementMark>(m_pNewBlocker));
804 return nId;
807 /* XSAXEventKeeper */
808 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
810 return createElementCollector(
811 css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY,
812 false,
813 nullptr);
816 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
818 markElementMarkBuffer(id);
821 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
823 return createBlocker();
826 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
828 markElementMarkBuffer(id);
831 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
833 return (m_pCurrentBlockingBufferNode != nullptr);
836 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
837 SAXEventKeeperImpl::getElement( sal_Int32 id )
839 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
841 ElementMark* pElementMark = findElementMarkBuffer(id);
842 if (pElementMark != nullptr)
844 rc = pElementMark->getBufferNode()->getXMLElement();
847 return rc;
850 void SAL_CALL SAXEventKeeperImpl::setElement(
851 sal_Int32 id,
852 const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement )
854 if (aElement.is())
856 m_xXMLDocument->rebuildIDLink(aElement);
858 ElementMark* pElementMark = findElementMarkBuffer(id);
860 if (pElementMark != nullptr)
862 BufferNode* pBufferNode = pElementMark->getBufferNode();
863 if (pBufferNode != nullptr)
865 const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
866 pBufferNode->setXMLElement(aElement);
868 if (bIsCurrent)
870 m_xXMLDocument->setCurrentElement(aElement);
875 else
877 removeElementCollector( id );
881 css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
882 const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler )
884 css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler;
886 m_xNextHandler = xNewHandler;
887 return xOldHandler;
890 OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
892 OUString rc = "ElementMarkBuffers: size = "
893 + OUString::number(m_vElementMarkBuffers.size())
894 + "\nCurrentBufferNode: "
895 + m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement())
896 + "\n" + printBufferNode(m_pRootBufferNode.get(), 0);
898 return rc;
901 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
903 css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
905 if (m_pCurrentBlockingBufferNode != nullptr)
907 rc = m_pCurrentBlockingBufferNode->getXMLElement();
910 return rc;
913 /* XSecuritySAXEventKeeper */
914 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
915 css::xml::crypto::sax::ElementMarkPriority priority,
916 sal_Bool modifyElement )
918 return createElementCollector(
919 priority,
920 modifyElement,
921 nullptr);
924 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
926 ElementMark* pElementMark = findElementMarkBuffer(id);
927 if (pElementMark != nullptr)
929 pElementMark->setSecurityId(securityId);
934 /* XReferenceResolvedBroadcaster */
935 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
936 sal_Int32 referenceId,
937 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener )
939 ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
940 if (pElementCollector != nullptr)
942 pElementCollector->setReferenceResolvedListener(listener);
946 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
947 sal_Int32 /*referenceId*/,
948 const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&)
952 /* XSAXEventKeeperStatusChangeBroadcaster */
953 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
954 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener )
956 m_xSAXEventKeeperStatusChangeListener = listener;
959 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
960 const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&)
964 /* XDocumentHandler */
965 void SAL_CALL SAXEventKeeperImpl::startDocument( )
967 if ( m_xNextHandler.is())
969 m_xNextHandler->startDocument();
973 void SAL_CALL SAXEventKeeperImpl::endDocument( )
975 if ( m_xNextHandler.is())
977 m_xNextHandler->endDocument();
981 void SAL_CALL SAXEventKeeperImpl::startElement(
982 const OUString& aName,
983 const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
986 * If there is a following handler and no blocking now, then
987 * forward this event
989 if ((m_pCurrentBlockingBufferNode == nullptr) &&
990 (m_xNextHandler.is()) &&
991 (!m_bIsForwarding) &&
992 (m_pNewBlocker == nullptr))
994 m_xNextHandler->startElement(aName, xAttribs);
997 * If not forwarding, buffer this startElement.
999 if (!m_bIsForwarding)
1001 sal_Int32 nLength = xAttribs->getLength();
1002 css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength);
1004 for ( int i = 0; i<nLength; ++i )
1006 aAttributes[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
1007 aAttributes[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i));
1010 m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes);
1013 BufferNode* pBufferNode = addNewElementMarkBuffers();
1014 if (pBufferNode != nullptr)
1016 setCurrentBufferNode(pBufferNode);
1020 void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName )
1022 const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1025 * If there is a following handler and no blocking now, then
1026 * forward this event
1028 if ((m_pCurrentBlockingBufferNode == nullptr) &&
1029 (m_xNextHandler.is()) &&
1030 (!m_bIsForwarding))
1032 m_xNextHandler->endElement(aName);
1035 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1036 (m_pCurrentBufferNode != m_pRootBufferNode.get()) ||
1037 (!m_xXMLDocument->isCurrentElementEmpty()))
1039 if (!m_bIsForwarding)
1041 m_xCompressedDocumentHandler->compressedEndElement(aName);
1045 * If the current buffer node has not notified yet, and
1046 * the current buffer node is waiting for the current element,
1047 * then let it notify.
1049 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1051 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1052 m_pCurrentBufferNode = const_cast<BufferNode*>(m_pCurrentBufferNode->getParent());
1054 pOldCurrentBufferNode->setReceivedAll();
1056 if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) &&
1057 m_xSAXEventKeeperStatusChangeListener.is())
1059 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false);
1063 else
1065 if (!m_bIsForwarding)
1067 m_xXMLDocument->removeCurrentElement();
1072 void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars )
1074 if (m_bIsForwarding)
1075 return;
1077 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1079 m_xNextHandler->characters(aChars);
1082 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1083 (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1085 m_xCompressedDocumentHandler->compressedCharacters(aChars);
1089 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces )
1091 characters( aWhitespaces );
1094 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1095 const OUString& aTarget, const OUString& aData )
1097 if (m_bIsForwarding)
1098 return;
1100 if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
1102 m_xNextHandler->processingInstruction(aTarget, aData);
1105 if ((m_pCurrentBlockingBufferNode != nullptr) ||
1106 (m_pCurrentBufferNode != m_pRootBufferNode.get()))
1108 m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData);
1112 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&)
1116 /* XInitialization */
1117 void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
1119 OSL_ASSERT(aArguments.getLength() == 1);
1121 aArguments[0] >>= m_xXMLDocument;
1122 m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1123 m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
1125 m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) );
1126 m_pCurrentBufferNode = m_pRootBufferNode.get();
1129 OUString SAXEventKeeperImpl_getImplementationName ()
1131 return IMPLEMENTATION_NAME;
1134 css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( )
1136 css::uno::Sequence<OUString> aRet { "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
1137 return aRet;
1140 /* XServiceInfo */
1141 OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1143 return SAXEventKeeperImpl_getImplementationName();
1146 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName )
1148 return cppu::supportsService(this, rServiceName);
1151 css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1153 return SAXEventKeeperImpl_getSupportedServiceNames();
1156 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */