Bump version to 5.0-14
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blob652b0f18b6ecbb3342946b91b386dc332d063ebb
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 "saxeventkeeperimpl.hxx"
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
24 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <osl/diagnose.h>
28 namespace cssu = com::sun::star::uno;
29 namespace cssl = com::sun::star::lang;
30 namespace cssxc = com::sun::star::xml::crypto;
31 namespace cssxcsax = com::sun::star::xml::csax;
32 namespace cssxw = com::sun::star::xml::wrapper;
33 namespace cssxs = com::sun::star::xml::sax;
35 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
37 #define _USECOMPRESSEDDOCUMENTHANDLER
39 SAXEventKeeperImpl::SAXEventKeeperImpl( )
40 :m_pRootBufferNode(NULL),
41 m_pCurrentBufferNode(NULL),
42 m_nNextElementMarkId(1),
43 m_pNewBlocker(NULL),
44 m_pCurrentBlockingBufferNode(NULL),
45 m_bIsReleasing(false),
46 m_bIsForwarding(false)
48 m_vElementMarkBuffers.reserve(2);
49 m_vNewElementCollectors.reserve(2);
50 m_vReleasedElementMarkBuffers.reserve(2);
53 SAXEventKeeperImpl::~SAXEventKeeperImpl()
56 * delete the BufferNode tree
58 if (m_pRootBufferNode != NULL)
60 m_pRootBufferNode->freeAllChildren();
61 delete m_pRootBufferNode;
64 m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
67 * delete all unfreed ElementMarks
69 m_vNewElementCollectors.clear();
70 m_pNewBlocker = NULL;
72 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
73 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
75 delete (*ii);
77 m_vElementMarkBuffers.clear();
80 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
81 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
83 * NAME
84 * setCurrentBufferNode -- set a new active BufferNode.
86 * SYNOPSIS
87 * setCurrentBufferNode( pBufferNode );
89 * FUNCTION
90 * connects this BufferNode into the BufferNode tree as a child of the
91 * current active BufferNode. Then makes this BufferNode as the current
92 * active BufferNode.
93 * If the previous active BufferNode points to the root
94 * BufferNode, which means that no buffering operation was proceeding,
95 * then notifies the status change listener that buffering operation
96 * will begin at once.
98 * INPUTS
99 * pBufferNode - a BufferNode which will be the new active BufferNode
101 * RESULT
102 * empty
104 * AUTHOR
105 * Michael Mi
106 * Email: michael.mi@sun.com
107 ******************************************************************************/
109 if (pBufferNode != m_pCurrentBufferNode)
111 if ( m_pCurrentBufferNode == m_pRootBufferNode &&
112 m_xSAXEventKeeperStatusChangeListener.is())
114 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
117 if (pBufferNode->getParent() == NULL)
119 m_pCurrentBufferNode->addChild(pBufferNode);
120 pBufferNode->setParent(m_pCurrentBufferNode);
123 m_pCurrentBufferNode = pBufferNode;
127 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
128 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
130 * NAME
131 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
133 * SYNOPSIS
134 * pBufferNode = addNewElementMarkBuffers( );
136 * FUNCTION
137 * if there are new ElementCollector or new Blocker to be added, then
138 * connect all of them with the current BufferNode. In case of the
139 * current BufferNode doesn't exist, creates one.
140 * Clears up the new ElementCollector list and the new Blocker pointer.
142 * INPUTS
143 * empty
145 * RESULT
146 * pBufferNode - the BufferNode that has been connected with both new
147 * ElementCollectors and new Blocker.
149 * AUTHOR
150 * Michael Mi
151 * Email: michael.mi@sun.com
152 ******************************************************************************/
154 BufferNode* pBufferNode = NULL;
156 if (m_pNewBlocker || !m_vNewElementCollectors.empty() )
159 * When the current BufferNode is right pointing to the current
160 * working element in the XMLDocumentWrapper component, then
161 * no new BufferNode is needed to create.
162 * This situation can only happen in the "Forwarding" mode.
164 if ( (m_pCurrentBufferNode != NULL) &&
165 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
167 pBufferNode = m_pCurrentBufferNode;
169 else
171 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
174 if (m_pNewBlocker != NULL)
176 pBufferNode->setBlocker(m_pNewBlocker);
179 * If no blocking before, then notify the status change listener that
180 * the SAXEventKeeper has entered "blocking" status, during which, no
181 * SAX events will be forwarded to the next document handler.
183 if (m_pCurrentBlockingBufferNode == NULL)
185 m_pCurrentBlockingBufferNode = pBufferNode;
187 if (m_xSAXEventKeeperStatusChangeListener.is())
189 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
193 m_pNewBlocker = NULL;
196 if (!m_vNewElementCollectors.empty())
198 std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
200 for( ; ii != m_vNewElementCollectors.end(); ++ii )
202 pBufferNode->addElementCollector(*ii);
205 m_vNewElementCollectors.clear();
209 return pBufferNode;
212 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
213 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
215 * NAME
216 * findElementMarkBuffer -- finds an ElementMark.
218 * SYNOPSIS
219 * pElementMark = findElementMarkBuffer( nId );
221 * FUNCTION
222 * searches an ElementMark with the particular Id in the ElementMark
223 * list.
225 * INPUTS
226 * nId - the Id of the ElementMark to be searched.
228 * RESULT
229 * pElementMark - the ElementMark with the particular Id, or NULL when
230 * no such Id exists.
232 * AUTHOR
233 * Michael Mi
234 * Email: michael.mi@sun.com
235 ******************************************************************************/
237 ElementMark* pElementMark = NULL;
239 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
241 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
243 if ( nId == (*ii)->getBufferId())
245 pElementMark = const_cast<ElementMark*>(*ii);
246 break;
250 return pElementMark;
253 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
254 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
256 * NAME
257 * removeElementMarkBuffer -- removes an ElementMark
259 * SYNOPSIS
260 * removeElementMarkBuffer( nId );
262 * FUNCTION
263 * removes an ElementMark with the particular Id in the ElementMark list.
265 * INPUTS
266 * nId - the Id of the ElementMark to be removed.
268 * RESULT
269 * empty
271 * AUTHOR
272 * Michael Mi
273 * Email: michael.mi@sun.com
274 ******************************************************************************/
276 std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
278 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
280 if ( nId == (*ii)->getBufferId())
283 * checks whether this ElementMark still in the new ElementCollect array
285 std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
286 for( ; jj != m_vNewElementCollectors.end(); ++jj )
288 if ((*ii) == (*jj))
290 m_vNewElementCollectors.erase(jj);
291 break;
296 * checks whether this ElementMark is the new Blocker
298 if ((*ii) == m_pNewBlocker)
300 m_pNewBlocker = NULL;
304 * destroy the ElementMark
306 delete (*ii);
308 m_vElementMarkBuffers.erase( ii );
309 break;
314 OUString SAXEventKeeperImpl::printBufferNode(
315 BufferNode* pBufferNode, sal_Int32 nIndent) const
316 /****** SAXEventKeeperImpl/printBufferNode ***********************************
318 * NAME
319 * printBufferNode -- retrieves the information of a BufferNode and its
320 * branch.
322 * SYNOPSIS
323 * info = printBufferNode( pBufferNode, nIndent );
325 * FUNCTION
326 * all retrieved information includes:
327 * 1. whether it is the current BufferNode;
328 * 2. whether it is the current blocking BufferNode;
329 * 3. the name of the parent element;
330 * 4. the name of this element;
331 * 5. all ElementCollectors working on this BufferNode;
332 * 6. the Blocker working on this BufferNode;
333 * 7. all child BufferNodes' information.
335 * INPUTS
336 * pBufferNode - the BufferNode from where information will be retrieved.
337 * nIndent - how many space characters prefixed before the output
338 * message.
340 * RESULT
341 * info - the information string
343 * AUTHOR
344 * Michael Mi
345 * Email: michael.mi@sun.com
346 ******************************************************************************/
348 OUString rc;
350 for ( int i=0; i<nIndent; ++i )
352 rc += OUString( " " );
355 if (pBufferNode == m_pCurrentBufferNode)
357 rc += OUString( "[%]" );
360 if (pBufferNode == m_pCurrentBlockingBufferNode)
362 rc += OUString( "[B]" );
365 rc += OUString( " " );
366 rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
368 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
369 if (pParent != NULL)
371 rc += OUString( "[" );
372 rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
373 rc += OUString( "]" );
376 rc += OUString( ":EC=" );
377 rc += pBufferNode->printChildren();
378 rc += OUString( " BR=" );
380 ElementMark * pBlocker = pBufferNode->getBlocker();
381 if (pBlocker != NULL)
383 rc += OUString::number( pBlocker->getBufferId() );
384 rc += OUString( "(SecId=" );
385 rc += OUString::number( pBlocker->getSecurityId() );
386 rc += OUString( ")" );
387 rc += OUString( " " );
389 rc += OUString( "\n" );
391 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
392 std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
393 for( ; jj != vChildren->end(); ++jj )
395 rc += printBufferNode(const_cast<BufferNode *>(*jj), nIndent+4);
398 delete vChildren;
400 return rc;
403 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
404 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode)
405 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
407 * NAME
408 * collectChildWorkingElement -- collects a BufferNode's all child
409 * Elements.
411 * SYNOPSIS
412 * list = collectChildWorkingElement( pBufferNode );
414 * FUNCTION
415 * see NAME.
417 * INPUTS
418 * pBufferNode - the BufferNode whose child Elements will be collected.
420 * RESULT
421 * list - the child Elements list.
423 * AUTHOR
424 * Michael Mi
425 * Email: michael.mi@sun.com
426 ******************************************************************************/
428 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
430 cssu::Sequence < cssu::Reference<
431 cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
433 std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
435 sal_Int32 nIndex = 0;
436 for( ; ii != vChildren->end(); ++ii )
438 aChildrenCollection[nIndex] = (*ii)->getXMLElement();
439 nIndex++;
442 delete vChildren;
444 return aChildrenCollection;
447 void SAXEventKeeperImpl::smashBufferNode(
448 BufferNode* pBufferNode, bool bClearRoot) const
449 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
451 * NAME
452 * smashBufferNode -- removes a BufferNode along with its working
453 * element.
455 * SYNOPSIS
456 * smashBufferNode( pBufferNode, bClearRoot );
458 * FUNCTION
459 * removes the BufferNode's working element from the DOM document, while
460 * reserves all ancestor paths for its child BufferNodes.
461 * when any of the BufferNode's ancestor element is useless, removes it
462 * too.
463 * removes the BufferNode from the BufferNode tree.
465 * INPUTS
466 * pBufferNode - the BufferNode to be removed
467 * bClearRoot - whether the root element also needs to be cleared up.
469 * RESULT
470 * empty
472 * NOTES
473 * when removeing a Blocker's BufferNode, the bClearRoot flag should be
474 * true. Because a Blocker can buffer many SAX events which are not used
475 * by any other ElementCollector or Blocker.
476 * When the bClearRoot is set to true, the root BufferNode will be first
477 * cleared, with a stop flag seting at the next Blocking BufferNode. This
478 * operation can delete all useless bufferred SAX events which are only
479 * needed by the Blocker to be deleted.
481 * AUTHOR
482 * Michael Mi
483 * Email: michael.mi@sun.com
484 ******************************************************************************/
486 if (!pBufferNode->hasAnything())
488 BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
491 * delete the XML data
493 if (pParent == m_pRootBufferNode)
495 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
496 bool bIsBlockInside = false;
497 bool bIsBlockingAfterward = false;
500 * If this is a blocker, then remove any out-element data
501 * which caused by blocking. The removal process will stop
502 * at the next blokcer to avoid removing any useful data.
504 if (bClearRoot)
506 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
507 aChildElements = collectChildWorkingElement(m_pRootBufferNode);
510 * the clearUselessData only clearup the content in the
511 * node, not the node itself.
513 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
514 aChildElements,
515 bIsNotBlocking?(NULL):
516 (m_pCurrentBlockingBufferNode->getXMLElement()));
519 * remove the node if it is empty, then if its parent is also
520 * empty, remove it, then if the next parent is also empty,
521 * remove it,..., until parent become null.
523 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
527 * if blocking, check the relationship between this BufferNode and
528 * the current blocking BufferNode.
530 if ( !bIsNotBlocking )
533 * the current blocking BufferNode is a descendant of this BufferNode.
535 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
538 * the current blocking BufferNode locates behind this BufferNode in tree
539 * order.
541 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
545 * this BufferNode's working element needs to be deleted only when
546 * 1. there is no blocking, or
547 * 2. the current blocking BufferNode is a descendant of this BufferNode,
548 * (then in the BufferNode's working element, the useless data before the blocking
549 * element should be deleted.) or
550 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
551 * (then the useless data between the blocking element and the working element
552 * should be deleted.).
553 * Otherwise, this working element should not be deleted.
555 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
557 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
558 aChildElements = collectChildWorkingElement(pBufferNode);
561 * the clearUselessData only clearup the content in the
562 * node, not the node itself.
564 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
565 aChildElements,
566 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
567 (NULL));
570 * remove the node if it is empty, then if its parent is also
571 * empty, remove it, then if the next parent is also empty,
572 * remove it,..., until parent become null.
574 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
578 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
580 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
581 pParent->removeChild(pBufferNode);
582 pBufferNode->setParent(NULL);
584 std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
585 for( ; ii != vChildren->end(); ++ii )
587 const_cast<BufferNode *>(*ii)->setParent(pParent);
588 pParent->addChild(*ii, nIndex);
589 nIndex++;
592 delete vChildren;
595 * delete the BufferNode
597 delete pBufferNode;
601 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
602 BufferNode* pStartBufferNode)
603 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
605 * NAME
606 * findNextBlockingBufferNode -- finds the next blocking BufferNode
607 * behind the particular BufferNode.
609 * SYNOPSIS
610 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
612 * FUNCTION
613 * see NAME.
615 * INPUTS
616 * pStartBufferNode - the BufferNode from where to search the next
617 * blocking BufferNode.
619 * RESULT
620 * pBufferNode - the next blocking BufferNode, or NULL if no such
621 * BufferNode exists.
623 * AUTHOR
624 * Michael Mi
625 * Email: michael.mi@sun.com
626 ******************************************************************************/
628 BufferNode* pNext = NULL;
630 if (pStartBufferNode != NULL)
632 pNext = pStartBufferNode;
634 while (NULL != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder())))
636 if (pNext->getBlocker() != NULL)
638 break;
643 return pNext;
646 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode)
647 /****** SAXEventKeeperImpl/diffuse *******************************************
649 * NAME
650 * diffuse -- diffuse the notification.
652 * SYNOPSIS
653 * diffuse( pBufferNode );
655 * FUNCTION
656 * diffuse the collecting completion notification from the specific
657 * BufferNode along its parent link, until an ancestor which is not
658 * completely received is met.
660 * INPUTS
661 * pBufferNode - the BufferNode from which the notification will be
662 * diffused.
664 * RESULT
665 * empty
667 * AUTHOR
668 * Michael Mi
669 * Email: michael.mi@sun.com
670 ******************************************************************************/
672 BufferNode* pParent = pBufferNode;
674 while(pParent->isAllReceived())
676 pParent->elementCollectorNotify();
677 pParent = const_cast<BufferNode*>(pParent->getParent());
681 void SAXEventKeeperImpl::releaseElementMarkBuffer()
682 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
684 * NAME
685 * releaseElementMarkBuffer -- releases useless ElementMarks
687 * SYNOPSIS
688 * releaseElementMarkBuffer( );
690 * FUNCTION
691 * releases each ElementMark in the releasing list
692 * m_vReleasedElementMarkBuffers.
693 * The operation differs between an ElementCollector and a Blocker.
695 * INPUTS
696 * empty
698 * RESULT
699 * empty
701 * AUTHOR
702 * Michael Mi
703 * Email: michael.mi@sun.com
704 ******************************************************************************/
706 m_bIsReleasing = true;
707 while (!m_vReleasedElementMarkBuffers.empty())
709 std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
710 sal_Int32 nId = *pId;
711 m_vReleasedElementMarkBuffers.erase( pId );
713 ElementMark* pElementMark = findElementMarkBuffer(nId);
715 if (pElementMark != NULL)
717 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
718 == pElementMark->getType())
720 * it is a EC
723 ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark);
725 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
727 * Delete the EC from the buffer node.
729 BufferNode* pBufferNode = pElementCollector->getBufferNode();
730 pBufferNode->removeElementCollector(pElementCollector);
732 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
734 pBufferNode->notifyBranch();
738 * delete the ElementMark
740 pElementCollector = NULL;
741 pElementMark = NULL;
742 removeElementMarkBuffer(nId);
745 * delete the BufferNode
747 diffuse(pBufferNode);
748 smashBufferNode(pBufferNode, false);
750 else
752 * it is a Blocker
756 * Delete the TH from the buffer node.
758 BufferNode *pBufferNode = pElementMark->getBufferNode();
759 pBufferNode->setBlocker(NULL);
762 * If there is a following handler and no blocking now, then
763 * forward this event
765 if (m_pCurrentBlockingBufferNode == pBufferNode)
768 * Before forwarding, the next blocking point needs to be
769 * found.
771 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
774 * Forward the blocked events between these two STHs.
776 if (m_xNextHandler.is())
778 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
779 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
781 m_pCurrentBufferNode = pBufferNode;
782 m_pCurrentBlockingBufferNode = NULL;
784 m_bIsForwarding = true;
786 m_xXMLDocument->generateSAXEvents(
787 m_xNextHandler,
788 this,
789 pBufferNode->getXMLElement(),
790 (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
792 m_bIsForwarding = false;
794 m_pCurrentBufferNode = pTempCurrentBufferNode;
795 if (m_pCurrentBlockingBufferNode == NULL)
797 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
801 if (m_pCurrentBlockingBufferNode == NULL &&
802 m_xSAXEventKeeperStatusChangeListener.is())
804 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
809 * delete the ElementMark
811 pElementMark = NULL;
812 removeElementMarkBuffer(nId);
815 * delete the BufferNode
817 diffuse(pBufferNode);
818 smashBufferNode(pBufferNode, true);
823 m_bIsReleasing = false;
825 if (!m_pRootBufferNode->hasAnything() &&
826 !m_pRootBufferNode->hasChildren() &&
827 m_xSAXEventKeeperStatusChangeListener.is())
829 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
833 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
834 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
836 * NAME
837 * markElementMarkBuffer -- marks an ElementMark to be released
839 * SYNOPSIS
840 * markElementMarkBuffer( nId );
842 * FUNCTION
843 * puts the ElementMark with the particular Id into the releasing list,
844 * checks whether the releasing process is running, if not then launch
845 * this process.
847 * INPUTS
848 * nId - the Id of the ElementMark which will be released
850 * RESULT
851 * empty
853 * AUTHOR
854 * Michael Mi
855 * Email: michael.mi@sun.com
856 ******************************************************************************/
858 m_vReleasedElementMarkBuffers.push_back( nId );
859 if ( !m_bIsReleasing )
861 releaseElementMarkBuffer();
865 sal_Int32 SAXEventKeeperImpl::createElementCollector(
866 sal_Int32 nSecurityId,
867 cssxc::sax::ElementMarkPriority nPriority,
868 bool bModifyElement,
869 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
870 /****** SAXEventKeeperImpl/createElementCollector ****************************
872 * NAME
873 * createElementCollector -- creates a new ElementCollector on the
874 * incoming element.
876 * SYNOPSIS
877 * nId = createElementCollector( nSecurityId, nPriority,
878 * bModifyElement,
879 * xReferenceResolvedListener );
881 * FUNCTION
882 * allocs a new Id, then create an ElementCollector with this Id value.
883 * Add the new created ElementCollector to the new ElementCollecotor list.
885 * INPUTS
886 * nSecurityId - the security Id of the new ElementCollector
887 * nPriority - the prirority of the new ElementCollector
888 * bModifyElement -whether this BufferNode will modify the content of
889 * the corresponding element it works on
890 * xReferenceResolvedListener - the listener for the new ElementCollector.
892 * RESULT
893 * nId - the Id of the new ElementCollector
895 * AUTHOR
896 * Michael Mi
897 * Email: michael.mi@sun.com
898 ******************************************************************************/
900 sal_Int32 nId = m_nNextElementMarkId;
901 m_nNextElementMarkId ++;
903 ElementCollector* pElementCollector
904 = new ElementCollector(
905 nSecurityId,
906 nId,
907 nPriority,
908 bModifyElement,
909 xReferenceResolvedListener);
911 m_vElementMarkBuffers.push_back( pElementCollector );
914 * All the new EC to initial EC array.
916 m_vNewElementCollectors.push_back( pElementCollector );
918 return nId;
922 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
923 /****** SAXEventKeeperImpl/createBlocker *************************************
925 * NAME
926 * createBlocker -- creates a new Blocker on the incoming element.
928 * SYNOPSIS
929 * nId = createBlocker( nSecurityId );
931 * FUNCTION
932 * see NAME.
934 * INPUTS
935 * nSecurityId - the security Id of the new Blocker
937 * RESULT
938 * nId - the Id of the new Blocker
940 * AUTHOR
941 * Michael Mi
942 * Email: michael.mi@sun.com
943 ******************************************************************************/
945 sal_Int32 nId = m_nNextElementMarkId;
946 m_nNextElementMarkId ++;
948 OSL_ASSERT(m_pNewBlocker == NULL);
950 m_pNewBlocker = new ElementMark(nSecurityId, nId);
951 m_vElementMarkBuffers.push_back( m_pNewBlocker );
953 return nId;
956 /* XSAXEventKeeper */
957 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
958 throw (cssu::RuntimeException, std::exception)
960 return createElementCollector(
961 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
962 cssxc::sax::ElementMarkPriority_AFTERMODIFY,
963 false,
964 NULL);
967 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
968 throw (cssu::RuntimeException, std::exception)
970 markElementMarkBuffer(id);
973 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
974 throw (cssu::RuntimeException, std::exception)
976 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
979 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
980 throw (cssu::RuntimeException, std::exception)
982 markElementMarkBuffer(id);
985 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
986 throw (cssu::RuntimeException, std::exception)
988 return (m_pCurrentBlockingBufferNode != NULL);
991 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
992 SAXEventKeeperImpl::getElement( sal_Int32 id )
993 throw (cssu::RuntimeException, std::exception)
995 cssu::Reference< cssxw::XXMLElementWrapper > rc;
997 ElementMark* pElementMark = findElementMarkBuffer(id);
998 if (pElementMark != NULL)
1000 rc = pElementMark->getBufferNode()->getXMLElement();
1003 return rc;
1006 void SAL_CALL SAXEventKeeperImpl::setElement(
1007 sal_Int32 id,
1008 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1009 throw (cssu::RuntimeException, std::exception)
1011 if (aElement.is())
1013 m_xXMLDocument->rebuildIDLink(aElement);
1015 ElementMark* pElementMark = findElementMarkBuffer(id);
1017 if (pElementMark != NULL)
1019 BufferNode* pBufferNode = pElementMark->getBufferNode();
1020 if (pBufferNode != NULL)
1022 bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1023 pBufferNode->setXMLElement(aElement);
1025 if (bIsCurrent)
1027 m_xXMLDocument->setCurrentElement(aElement);
1032 else
1034 removeElementCollector( id );
1038 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1039 const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1040 throw (cssu::RuntimeException, std::exception)
1042 cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1044 m_xNextHandler = xNewHandler;
1045 return xOldHandler;
1048 OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1049 throw (cssu::RuntimeException, std::exception)
1051 OUString rc;
1053 rc += OUString( "ElementMarkBuffers: size = " );
1054 rc += OUString::number(m_vElementMarkBuffers.size());
1055 rc += OUString( "\nCurrentBufferNode: " );
1056 rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1057 rc += OUString( "\n" );
1058 rc += printBufferNode(m_pRootBufferNode, 0);
1060 return rc;
1063 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1064 throw (cssu::RuntimeException, std::exception)
1066 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1068 if (m_pCurrentBlockingBufferNode != NULL)
1070 rc = m_pCurrentBlockingBufferNode->getXMLElement();
1073 return rc;
1076 /* XSecuritySAXEventKeeper */
1077 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1078 cssxc::sax::ElementMarkPriority priority,
1079 sal_Bool modifyElement )
1080 throw (cssu::RuntimeException, std::exception)
1082 return createElementCollector(
1083 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1084 priority,
1085 modifyElement,
1086 NULL);
1089 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1090 sal_Int32 referenceId,
1091 cssxc::sax::ElementMarkPriority priority )
1092 throw (cssu::RuntimeException, std::exception)
1094 sal_Int32 nId = -1;
1096 ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
1097 if (pElementCollector != NULL)
1099 nId = m_nNextElementMarkId;
1100 m_nNextElementMarkId ++;
1102 ElementCollector* pClonedOne
1103 = pElementCollector->clone(nId, priority);
1106 * add this EC into the security data buffer array.
1108 m_vElementMarkBuffers.push_back(pClonedOne);
1111 * If the reference EC is still in initial EC array, add
1112 * this cloned one into the initial EC array too.
1114 if (pElementCollector->getBufferNode() == NULL)
1116 m_vNewElementCollectors.push_back(pClonedOne);
1120 return nId;
1123 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1124 throw (cssu::RuntimeException, std::exception)
1126 ElementMark* pElementMark = findElementMarkBuffer(id);
1127 if (pElementMark != NULL)
1129 pElementMark->setSecurityId(securityId);
1134 /* XReferenceResolvedBroadcaster */
1135 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1136 sal_Int32 referenceId,
1137 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1138 throw (cssu::RuntimeException, std::exception)
1140 ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
1141 if (pElementCollector != NULL)
1143 pElementCollector->setReferenceResolvedListener(listener);
1147 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1148 sal_Int32 /*referenceId*/,
1149 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1150 throw (cssu::RuntimeException, std::exception)
1154 /* XSAXEventKeeperStatusChangeBroadcaster */
1155 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1156 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1157 throw (cssu::RuntimeException, std::exception)
1159 m_xSAXEventKeeperStatusChangeListener = listener;
1162 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1163 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1164 throw (cssu::RuntimeException, std::exception)
1168 /* XDocumentHandler */
1169 void SAL_CALL SAXEventKeeperImpl::startDocument( )
1170 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1172 if ( m_xNextHandler.is())
1174 m_xNextHandler->startDocument();
1178 void SAL_CALL SAXEventKeeperImpl::endDocument( )
1179 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1181 if ( m_xNextHandler.is())
1183 m_xNextHandler->endDocument();
1187 void SAL_CALL SAXEventKeeperImpl::startElement(
1188 const OUString& aName,
1189 const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1190 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1193 * If there is a following handler and no blocking now, then
1194 * forward this event
1196 if ((m_pCurrentBlockingBufferNode == NULL) &&
1197 (m_xNextHandler.is()) &&
1198 (!m_bIsForwarding) &&
1199 (m_pNewBlocker == NULL))
1201 m_xNextHandler->startElement(aName, xAttribs);
1205 * If not forwarding, buffer this startElement.
1207 if (!m_bIsForwarding)
1209 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1210 m_xDocumentHandler->startElement(aName, xAttribs);
1211 #else
1212 sal_Int32 nLength = xAttribs->getLength();
1213 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1215 for ( int i = 0; i<nLength; ++i )
1217 aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1218 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1221 m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes);
1222 #endif
1226 BufferNode* pBufferNode = addNewElementMarkBuffers();
1227 if (pBufferNode != NULL)
1229 setCurrentBufferNode(pBufferNode);
1233 void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName )
1234 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1236 bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1239 * If there is a following handler and no blocking now, then
1240 * forward this event
1242 if ((m_pCurrentBlockingBufferNode == NULL) &&
1243 (m_xNextHandler.is()) &&
1244 (!m_bIsForwarding))
1246 m_xNextHandler->endElement(aName);
1249 if ((m_pCurrentBlockingBufferNode != NULL) ||
1250 (m_pCurrentBufferNode != m_pRootBufferNode) ||
1251 (!m_xXMLDocument->isCurrentElementEmpty()))
1253 if (!m_bIsForwarding)
1255 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1256 m_xDocumentHandler->endElement(aName);
1257 #else
1258 m_xCompressedDocumentHandler->compressedEndElement(aName);
1259 #endif
1263 * If the current buffer node has not notified yet, and
1264 * the current buffer node is waiting for the current element,
1265 * then let it notify.
1267 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1269 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1270 m_pCurrentBufferNode = const_cast<BufferNode*>(m_pCurrentBufferNode->getParent());
1272 pOldCurrentBufferNode->setReceivedAll();
1274 if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1275 m_xSAXEventKeeperStatusChangeListener.is())
1277 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1281 else
1283 if (!m_bIsForwarding)
1285 m_xXMLDocument->removeCurrentElement();
1290 void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars )
1291 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1293 if (!m_bIsForwarding)
1295 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1297 m_xNextHandler->characters(aChars);
1300 if ((m_pCurrentBlockingBufferNode != NULL) ||
1301 (m_pCurrentBufferNode != m_pRootBufferNode))
1303 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1304 m_xDocumentHandler->characters(aChars);
1305 #else
1306 m_xCompressedDocumentHandler->compressedCharacters(aChars);
1307 #endif
1312 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces )
1313 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1315 characters( aWhitespaces );
1318 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1319 const OUString& aTarget, const OUString& aData )
1320 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1322 if (!m_bIsForwarding)
1324 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1326 m_xNextHandler->processingInstruction(aTarget, aData);
1329 if ((m_pCurrentBlockingBufferNode != NULL) ||
1330 (m_pCurrentBufferNode != m_pRootBufferNode))
1332 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1333 m_xDocumentHandler->processingInstruction(aTarget, aData);
1334 #else
1335 m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData);
1336 #endif
1341 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1342 throw (cssxs::SAXException, cssu::RuntimeException, std::exception)
1346 /* XInitialization */
1347 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1348 throw (cssu::Exception, cssu::RuntimeException, std::exception)
1350 OSL_ASSERT(aArguments.getLength() == 1);
1352 aArguments[0] >>= m_xXMLDocument;
1353 m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1354 m_xXMLDocument, cssu::UNO_QUERY );
1355 m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1356 m_xXMLDocument, cssu::UNO_QUERY );
1358 m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1359 m_pCurrentBufferNode = m_pRootBufferNode;
1362 OUString SAXEventKeeperImpl_getImplementationName ()
1363 throw (cssu::RuntimeException)
1365 return OUString ( IMPLEMENTATION_NAME );
1368 cssu::Sequence< OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( )
1369 throw (cssu::RuntimeException)
1371 cssu::Sequence < OUString > aRet(1);
1372 OUString* pArray = aRet.getArray();
1373 pArray[0] = "com.sun.star.xml.crypto.sax.SAXEventKeeper";
1374 return aRet;
1377 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1378 const cssu::Reference< cssl::XMultiServiceFactory > &)
1379 throw( cssu::Exception )
1381 return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1384 /* XServiceInfo */
1385 OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1386 throw (cssu::RuntimeException, std::exception)
1388 return SAXEventKeeperImpl_getImplementationName();
1391 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName )
1392 throw (cssu::RuntimeException, std::exception)
1394 return cppu::supportsService(this, rServiceName);
1397 cssu::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1398 throw (cssu::RuntimeException, std::exception)
1400 return SAXEventKeeperImpl_getSupportedServiceNames();
1403 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */