merged tag ooo/OOO330_m14
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blobd5779e623522698584392bad21fdab711482233a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlsecurity.hxx"
31 #include "saxeventkeeperimpl.hxx"
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
34 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
36 namespace cssu = com::sun::star::uno;
37 namespace cssl = com::sun::star::lang;
38 namespace cssxc = com::sun::star::xml::crypto;
39 namespace cssxcsax = com::sun::star::xml::csax;
40 namespace cssxw = com::sun::star::xml::wrapper;
41 namespace cssxs = com::sun::star::xml::sax;
43 #define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
44 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
46 #define _USECOMPRESSEDDOCUMENTHANDLER
48 SAXEventKeeperImpl::SAXEventKeeperImpl( )
49 :m_pRootBufferNode(NULL),
50 m_pCurrentBufferNode(NULL),
51 m_nNextElementMarkId(1),
52 m_pNewBlocker(NULL),
53 m_pCurrentBlockingBufferNode(NULL),
54 m_bIsReleasing(false),
55 m_bIsForwarding(false)
57 m_vElementMarkBuffers.reserve(2);
58 m_vNewElementCollectors.reserve(2);
59 m_vReleasedElementMarkBuffers.reserve(2);
62 SAXEventKeeperImpl::~SAXEventKeeperImpl()
65 * delete the BufferNode tree
67 if (m_pRootBufferNode != NULL)
69 m_pRootBufferNode->freeAllChildren();
70 delete m_pRootBufferNode;
73 m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
76 * delete all unfreed ElementMarks
78 m_vNewElementCollectors.clear();
79 m_pNewBlocker = NULL;
81 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
82 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
84 delete (*ii);
86 m_vElementMarkBuffers.clear();
89 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
90 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
92 * NAME
93 * setCurrentBufferNode -- set a new active BufferNode.
95 * SYNOPSIS
96 * setCurrentBufferNode( pBufferNode );
98 * FUNCTION
99 * connects this BufferNode into the BufferNode tree as a child of the
100 * current active BufferNode. Then makes this BufferNode as the current
101 * active BufferNode.
102 * If the previous active BufferNode points to the root
103 * BufferNode, which means that no buffering operation was proceeding,
104 * then notifies the status change listener that buffering operation
105 * will begin at once.
107 * INPUTS
108 * pBufferNode - a BufferNode which will be the new active BufferNode
110 * RESULT
111 * empty
113 * HISTORY
114 * 05.01.2004 - implemented
116 * AUTHOR
117 * Michael Mi
118 * Email: michael.mi@sun.com
119 ******************************************************************************/
121 if (pBufferNode != m_pCurrentBufferNode)
123 if ( m_pCurrentBufferNode == m_pRootBufferNode &&
124 m_xSAXEventKeeperStatusChangeListener.is())
126 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
129 if (pBufferNode->getParent() == NULL)
131 m_pCurrentBufferNode->addChild(pBufferNode);
132 pBufferNode->setParent(m_pCurrentBufferNode);
135 m_pCurrentBufferNode = pBufferNode;
139 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
140 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
142 * NAME
143 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
145 * SYNOPSIS
146 * pBufferNode = addNewElementMarkBuffers( );
148 * FUNCTION
149 * if there are new ElementCollector or new Blocker to be added, then
150 * connect all of them with the current BufferNode. In case of the
151 * current BufferNode doesn't exist, creates one.
152 * Clears up the new ElementCollector list and the new Blocker pointer.
154 * INPUTS
155 * empty
157 * RESULT
158 * pBufferNode - the BufferNode that has been connected with both new
159 * ElementCollectors and new Blocker.
161 * HISTORY
162 * 05.01.2004 - implemented
164 * AUTHOR
165 * Michael Mi
166 * Email: michael.mi@sun.com
167 ******************************************************************************/
169 BufferNode* pBufferNode = NULL;
171 if ( (m_vNewElementCollectors.size()>0) ||
172 (m_pNewBlocker != NULL))
175 * When the current BufferNode is right pointing to the current
176 * working element in the XMLDocumentWrapper component, then
177 * no new BufferNode is needed to create.
178 * This situation can only happen in the "Forwarding" mode.
180 if ( (m_pCurrentBufferNode != NULL) &&
181 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
183 pBufferNode = m_pCurrentBufferNode;
185 else
187 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
190 if (m_pNewBlocker != NULL)
192 pBufferNode->setBlocker(m_pNewBlocker);
195 * If no blocking before, then notify the status change listener that
196 * the SAXEventKeeper has entered "blocking" status, during which, no
197 * SAX events will be forwarded to the next document handler.
199 if (m_pCurrentBlockingBufferNode == NULL)
201 m_pCurrentBlockingBufferNode = pBufferNode;
203 if (m_xSAXEventKeeperStatusChangeListener.is())
205 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
209 m_pNewBlocker = NULL;
212 if (m_vNewElementCollectors.size()>0)
214 std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
216 for( ; ii != m_vNewElementCollectors.end(); ++ii )
218 pBufferNode->addElementCollector(*ii);
221 m_vNewElementCollectors.clear();
225 return pBufferNode;
228 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
229 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
231 * NAME
232 * findElementMarkBuffer -- finds an ElementMark.
234 * SYNOPSIS
235 * pElementMark = findElementMarkBuffer( nId );
237 * FUNCTION
238 * searches an ElementMark with the particular Id in the ElementMark
239 * list.
241 * INPUTS
242 * nId - the Id of the ElementMark to be searched.
244 * RESULT
245 * pElementMark - the ElementMark with the particular Id, or NULL when
246 * no such Id exists.
248 * HISTORY
249 * 05.01.2004 - implemented
251 * AUTHOR
252 * Michael Mi
253 * Email: michael.mi@sun.com
254 ******************************************************************************/
256 ElementMark* pElementMark = NULL;
258 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
260 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
262 if ( nId == (*ii)->getBufferId())
264 pElementMark = (ElementMark*)*ii;
265 break;
269 return pElementMark;
272 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
273 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
275 * NAME
276 * removeElementMarkBuffer -- removes an ElementMark
278 * SYNOPSIS
279 * removeElementMarkBuffer( nId );
281 * FUNCTION
282 * removes an ElementMark with the particular Id in the ElementMark list.
284 * INPUTS
285 * nId - the Id of the ElementMark to be removed.
287 * RESULT
288 * empty
290 * HISTORY
291 * 05.01.2004 - implemented
293 * AUTHOR
294 * Michael Mi
295 * Email: michael.mi@sun.com
296 ******************************************************************************/
298 std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
300 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
302 if ( nId == (*ii)->getBufferId())
305 * checks whether this ElementMark still in the new ElementCollect array
307 std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
308 for( ; jj != m_vNewElementCollectors.end(); ++jj )
310 if ((*ii) == (*jj))
312 m_vNewElementCollectors.erase(jj);
313 break;
318 * checks whether this ElementMark is the new Blocker
320 if ((*ii) == m_pNewBlocker)
322 m_pNewBlocker = NULL;
326 * destory the ElementMark
328 delete (*ii);
330 m_vElementMarkBuffers.erase( ii );
331 break;
336 rtl::OUString SAXEventKeeperImpl::printBufferNode(
337 BufferNode* pBufferNode, sal_Int32 nIndent) const
338 /****** SAXEventKeeperImpl/printBufferNode ***********************************
340 * NAME
341 * printBufferNode -- retrieves the information of a BufferNode and its
342 * branch.
344 * SYNOPSIS
345 * info = printBufferNode( pBufferNode, nIndent );
347 * FUNCTION
348 * all retrieved information includes:
349 * 1. whether it is the current BufferNode;
350 * 2. whether it is the current blocking BufferNode;
351 * 3. the name of the parent element;
352 * 4. the name of this element;
353 * 5. all ElementCollectors working on this BufferNode;
354 * 6. the Blocker working on this BufferNode;
355 * 7. all child BufferNodes' information.
357 * INPUTS
358 * pBufferNode - the BufferNode from where information will be retrieved.
359 * nIndent - how many space characters prefixed before the output
360 * message.
362 * RESULT
363 * info - the information string
365 * HISTORY
366 * 05.01.2004 - implemented
368 * AUTHOR
369 * Michael Mi
370 * Email: michael.mi@sun.com
371 ******************************************************************************/
373 rtl::OUString rc;
375 for ( int i=0; i<nIndent; ++i )
377 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
380 if (pBufferNode == m_pCurrentBufferNode)
382 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
385 if (pBufferNode == m_pCurrentBlockingBufferNode)
387 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
390 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
391 rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
393 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
394 if (pParent != NULL)
396 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
397 rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
398 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
401 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
402 rc += pBufferNode->printChildren();
403 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));
405 ElementMark * pBlocker = pBufferNode->getBlocker();
406 if (pBlocker != NULL)
408 rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
409 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
410 rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
411 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
412 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
414 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
416 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
417 std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
418 for( ; jj != vChildren->end(); ++jj )
420 rc += printBufferNode((BufferNode *)*jj, nIndent+4);
423 delete vChildren;
425 return rc;
428 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
429 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
430 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
432 * NAME
433 * collectChildWorkingElement -- collects a BufferNode's all child
434 * Elements.
436 * SYNOPSIS
437 * list = collectChildWorkingElement( pBufferNode );
439 * FUNCTION
440 * see NAME.
442 * INPUTS
443 * pBufferNode - the BufferNode whose child Elements will be collected.
445 * RESULT
446 * list - the child Elements list.
448 * HISTORY
449 * 05.01.2004 - implemented
451 * AUTHOR
452 * Michael Mi
453 * Email: michael.mi@sun.com
454 ******************************************************************************/
456 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
458 cssu::Sequence < cssu::Reference<
459 cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
461 std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
463 sal_Int32 nIndex = 0;
464 for( ; ii != vChildren->end(); ++ii )
466 aChildrenCollection[nIndex] = (*ii)->getXMLElement();
467 nIndex++;
470 delete vChildren;
472 return aChildrenCollection;
475 void SAXEventKeeperImpl::smashBufferNode(
476 BufferNode* pBufferNode, bool bClearRoot) const
477 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
479 * NAME
480 * smashBufferNode -- removes a BufferNode along with its working
481 * element.
483 * SYNOPSIS
484 * smashBufferNode( pBufferNode, bClearRoot );
486 * FUNCTION
487 * removes the BufferNode's working element from the DOM document, while
488 * reserves all ancestor paths for its child BufferNodes.
489 * when any of the BufferNode's ancestor element is useless, removes it
490 * too.
491 * removes the BufferNode from the BufferNode tree.
493 * INPUTS
494 * pBufferNode - the BufferNode to be removed
495 * bClearRoot - whether the root element also needs to be cleared up.
497 * RESULT
498 * empty
500 * NOTES
501 * when removeing a Blocker's BufferNode, the bClearRoot flag should be
502 * true. Because a Blocker can buffer many SAX events which are not used
503 * by any other ElementCollector or Blocker.
504 * When the bClearRoot is set to true, the root BufferNode will be first
505 * cleared, with a stop flag seting at the next Blocking BufferNode. This
506 * operation can delete all useless bufferred SAX events which are only
507 * needed by the Blocker to be deleted.
509 * HISTORY
510 * 05.01.2004 - implemented
512 * AUTHOR
513 * Michael Mi
514 * Email: michael.mi@sun.com
515 ******************************************************************************/
517 if (!pBufferNode->hasAnything())
519 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
522 * delete the XML data
524 if (pParent == m_pRootBufferNode)
526 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
527 bool bIsBlockInside = false;
528 bool bIsBlockingAfterward = false;
531 * If this is a blocker, then remove any out-element data
532 * which caused by blocking. The removal process will stop
533 * at the next blokcer to avoid removing any useful data.
535 if (bClearRoot)
537 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
538 aChildElements = collectChildWorkingElement(m_pRootBufferNode);
541 * the clearUselessData only clearup the content in the
542 * node, not the node itself.
544 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
545 aChildElements,
546 bIsNotBlocking?(NULL):
547 (m_pCurrentBlockingBufferNode->getXMLElement()));
550 * remove the node if it is empty, then if its parent is also
551 * empty, remove it, then if the next parent is also empty,
552 * remove it,..., until parent become null.
554 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
558 * if blocking, check the relationship between this BufferNode and
559 * the current blocking BufferNode.
561 if ( !bIsNotBlocking )
564 * the current blocking BufferNode is a descendant of this BufferNode.
566 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
569 * the current blocking BufferNode locates behind this BufferNode in tree
570 * order.
572 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
576 * this BufferNode's working element needs to be deleted only when
577 * 1. there is no blocking, or
578 * 2. the current blocking BufferNode is a descendant of this BufferNode,
579 * (then in the BufferNode's working element, the useless data before the blocking
580 * element should be deleted.) or
581 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
582 * (then the useless data between the blocking element and the working element
583 * should be deleted.).
584 * Otherwise, this working element should not be deleted.
586 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
588 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
589 aChildElements = collectChildWorkingElement(pBufferNode);
592 * the clearUselessData only clearup the content in the
593 * node, not the node itself.
595 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
596 aChildElements,
597 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
598 (NULL));
601 * remove the node if it is empty, then if its parent is also
602 * empty, remove it, then if the next parent is also empty,
603 * remove it,..., until parent become null.
605 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
609 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
611 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
612 pParent->removeChild(pBufferNode);
613 pBufferNode->setParent(NULL);
615 std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
616 for( ; ii != vChildren->end(); ++ii )
618 ((BufferNode *)(*ii))->setParent(pParent);
619 pParent->addChild(*ii, nIndex);
620 nIndex++;
623 delete vChildren;
626 * delete the BufferNode
628 delete pBufferNode;
632 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
633 BufferNode* pStartBufferNode) const
634 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
636 * NAME
637 * findNextBlockingBufferNode -- finds the next blocking BufferNode
638 * behind the particular BufferNode.
640 * SYNOPSIS
641 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
643 * FUNCTION
644 * see NAME.
646 * INPUTS
647 * pStartBufferNode - the BufferNode from where to search the next
648 * blocking BufferNode.
650 * RESULT
651 * pBufferNode - the next blocking BufferNode, or NULL if no such
652 * BufferNode exists.
654 * HISTORY
655 * 05.01.2004 - implemented
657 * AUTHOR
658 * Michael Mi
659 * Email: michael.mi@sun.com
660 ******************************************************************************/
662 BufferNode* pNext = NULL;
664 if (pStartBufferNode != NULL)
666 pNext = pStartBufferNode;
668 while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
670 if (pNext->getBlocker() != NULL)
672 break;
677 return pNext;
680 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
681 /****** SAXEventKeeperImpl/diffuse *******************************************
683 * NAME
684 * diffuse -- diffuse the notification.
686 * SYNOPSIS
687 * diffuse( pBufferNode );
689 * FUNCTION
690 * diffuse the collecting completion notification from the specific
691 * BufferNode along its parent link, until an ancestor which is not
692 * completely received is met.
694 * INPUTS
695 * pBufferNode - the BufferNode from which the notification will be
696 * diffused.
698 * RESULT
699 * empty
701 * HISTORY
702 * 05.01.2004 - implemented
704 * AUTHOR
705 * Michael Mi
706 * Email: michael.mi@sun.com
707 ******************************************************************************/
709 BufferNode* pParent = pBufferNode;
711 while(pParent->isAllReceived())
713 pParent->elementCollectorNotify();
714 pParent = (BufferNode*)pParent->getParent();
718 void SAXEventKeeperImpl::releaseElementMarkBuffer()
719 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
721 * NAME
722 * releaseElementMarkBuffer -- releases useless ElementMarks
724 * SYNOPSIS
725 * releaseElementMarkBuffer( );
727 * FUNCTION
728 * releases each ElementMark in the releasing list
729 * m_vReleasedElementMarkBuffers.
730 * The operation differs between an ElementCollector and a Blocker.
732 * INPUTS
733 * empty
735 * RESULT
736 * empty
738 * HISTORY
739 * 05.01.2004 - implemented
741 * AUTHOR
742 * Michael Mi
743 * Email: michael.mi@sun.com
744 ******************************************************************************/
746 m_bIsReleasing = true;
747 while (m_vReleasedElementMarkBuffers.size()>0)
749 std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
750 sal_Int32 nId = *pId;
751 m_vReleasedElementMarkBuffers.erase( pId );
753 ElementMark* pElementMark = findElementMarkBuffer(nId);
755 if (pElementMark != NULL)
757 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
758 == pElementMark->getType())
760 * it is a EC
763 ElementCollector* pElementCollector = (ElementCollector*)pElementMark;
765 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
766 bool bToModify = pElementCollector->getModify();
769 * Delete the EC from the buffer node.
771 BufferNode* pBufferNode = pElementCollector->getBufferNode();
772 pBufferNode->removeElementCollector(pElementCollector);
774 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
776 pBufferNode->notifyBranch();
779 if (bToModify)
781 pBufferNode->notifyAncestor();
785 * delete the ElementMark
787 pElementCollector = NULL;
788 pElementMark = NULL;
789 removeElementMarkBuffer(nId);
792 * delete the BufferNode
794 diffuse(pBufferNode);
795 smashBufferNode(pBufferNode, false);
797 else
799 * it is a Blocker
803 * Delete the TH from the buffer node.
805 BufferNode *pBufferNode = pElementMark->getBufferNode();
806 pBufferNode->setBlocker(NULL);
809 * If there is a following handler and no blocking now, then
810 * forward this event
812 if (m_pCurrentBlockingBufferNode == pBufferNode)
815 * Before forwarding, the next blocking point needs to be
816 * found.
818 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
821 * Forward the blocked events between these two STHs.
823 if (m_xNextHandler.is())
825 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
826 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
828 m_pCurrentBufferNode = pBufferNode;
829 m_pCurrentBlockingBufferNode = NULL;
831 m_bIsForwarding = true;
833 m_xXMLDocument->generateSAXEvents(
834 m_xNextHandler,
835 this,
836 pBufferNode->getXMLElement(),
837 (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
839 m_bIsForwarding = false;
841 m_pCurrentBufferNode = pTempCurrentBufferNode;
842 if (m_pCurrentBlockingBufferNode == NULL)
844 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
848 if (m_pCurrentBlockingBufferNode == NULL &&
849 m_xSAXEventKeeperStatusChangeListener.is())
851 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
856 * delete the ElementMark
858 pElementMark = NULL;
859 removeElementMarkBuffer(nId);
862 * delete the BufferNode
864 diffuse(pBufferNode);
865 smashBufferNode(pBufferNode, true);
870 m_bIsReleasing = false;
872 if (!m_pRootBufferNode->hasAnything() &&
873 !m_pRootBufferNode->hasChildren() &&
874 m_xSAXEventKeeperStatusChangeListener.is())
876 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
880 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
881 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
883 * NAME
884 * markElementMarkBuffer -- marks an ElementMark to be released
886 * SYNOPSIS
887 * markElementMarkBuffer( nId );
889 * FUNCTION
890 * puts the ElementMark with the particular Id into the releasing list,
891 * checks whether the releasing process is runing, if not then launch
892 * this process.
894 * INPUTS
895 * nId - the Id of the ElementMark which will be released
897 * RESULT
898 * empty
900 * HISTORY
901 * 05.01.2004 - implemented
903 * AUTHOR
904 * Michael Mi
905 * Email: michael.mi@sun.com
906 ******************************************************************************/
908 m_vReleasedElementMarkBuffers.push_back( nId );
909 if ( !m_bIsReleasing )
911 releaseElementMarkBuffer();
915 sal_Int32 SAXEventKeeperImpl::createElementCollector(
916 sal_Int32 nSecurityId,
917 cssxc::sax::ElementMarkPriority nPriority,
918 bool bModifyElement,
919 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
920 /****** SAXEventKeeperImpl/createElementCollector ****************************
922 * NAME
923 * createElementCollector -- creates a new ElementCollector on the
924 * incoming element.
926 * SYNOPSIS
927 * nId = createElementCollector( nSecurityId, nPriority,
928 * bModifyElement,
929 * xReferenceResolvedListener );
931 * FUNCTION
932 * allocs a new Id, then create an ElementCollector with this Id value.
933 * Add the new created ElementCollector to the new ElementCollecotor list.
935 * INPUTS
936 * nSecurityId - the security Id of the new ElementCollector
937 * nPriority - the prirority of the new ElementCollector
938 * bModifyElement -whether this BufferNode will modify the content of
939 * the corresponding element it works on
940 * xReferenceResolvedListener - the listener for the new ElementCollector.
942 * RESULT
943 * nId - the Id of the new ElementCollector
945 * HISTORY
946 * 05.01.2004 - implemented
948 * AUTHOR
949 * Michael Mi
950 * Email: michael.mi@sun.com
951 ******************************************************************************/
953 sal_Int32 nId = m_nNextElementMarkId;
954 m_nNextElementMarkId ++;
956 ElementCollector* pElementCollector
957 = new ElementCollector(
958 nSecurityId,
959 nId,
960 nPriority,
961 bModifyElement,
962 xReferenceResolvedListener);
964 m_vElementMarkBuffers.push_back( pElementCollector );
967 * All the new EC to initial EC array.
969 m_vNewElementCollectors.push_back( pElementCollector );
971 return nId;
975 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
976 /****** SAXEventKeeperImpl/createBlocker *************************************
978 * NAME
979 * createBlocker -- creates a new Blocker on the incoming element.
981 * SYNOPSIS
982 * nId = createBlocker( nSecurityId );
984 * FUNCTION
985 * see NAME.
987 * INPUTS
988 * nSecurityId - the security Id of the new Blocker
990 * RESULT
991 * nId - the Id of the new Blocker
993 * HISTORY
994 * 05.01.2004 - implemented
996 * AUTHOR
997 * Michael Mi
998 * Email: michael.mi@sun.com
999 ******************************************************************************/
1001 sal_Int32 nId = m_nNextElementMarkId;
1002 m_nNextElementMarkId ++;
1004 OSL_ASSERT(m_pNewBlocker == NULL);
1006 m_pNewBlocker = new ElementMark(nSecurityId, nId);
1007 m_vElementMarkBuffers.push_back( m_pNewBlocker );
1009 return nId;
1012 /* XSAXEventKeeper */
1013 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
1014 throw (cssu::RuntimeException)
1016 return createElementCollector(
1017 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1018 cssxc::sax::ElementMarkPriority_AFTERMODIFY,
1019 false,
1020 NULL);
1023 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
1024 throw (cssu::RuntimeException)
1026 markElementMarkBuffer(id);
1029 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
1030 throw (cssu::RuntimeException)
1032 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
1035 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
1036 throw (cssu::RuntimeException)
1038 markElementMarkBuffer(id);
1041 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
1042 throw (cssu::RuntimeException)
1044 return (m_pCurrentBlockingBufferNode != NULL);
1047 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
1048 SAXEventKeeperImpl::getElement( sal_Int32 id )
1049 throw (cssu::RuntimeException)
1051 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1053 ElementMark* pElementMark = findElementMarkBuffer(id);
1054 if (pElementMark != NULL)
1056 rc = pElementMark->getBufferNode()->getXMLElement();
1059 return rc;
1062 void SAL_CALL SAXEventKeeperImpl::setElement(
1063 sal_Int32 id,
1064 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1065 throw (cssu::RuntimeException)
1067 if (aElement.is())
1069 m_xXMLDocument->rebuildIDLink(aElement);
1071 ElementMark* pElementMark = findElementMarkBuffer(id);
1073 if (pElementMark != NULL)
1075 BufferNode* pBufferNode = pElementMark->getBufferNode();
1076 if (pBufferNode != NULL)
1078 bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1079 pBufferNode->setXMLElement(aElement);
1081 if (bIsCurrent)
1083 m_xXMLDocument->setCurrentElement(aElement);
1088 else
1090 removeElementCollector( id );
1094 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1095 const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1096 throw (cssu::RuntimeException)
1098 cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1100 m_xNextHandler = xNewHandler;
1101 return xOldHandler;
1104 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1105 throw (cssu::RuntimeException)
1107 rtl::OUString rc;
1109 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
1110 rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
1111 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
1112 rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1113 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
1114 rc += printBufferNode(m_pRootBufferNode, 0);
1116 return rc;
1119 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1120 throw (cssu::RuntimeException)
1122 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1124 if (m_pCurrentBlockingBufferNode != NULL)
1126 rc = m_pCurrentBlockingBufferNode->getXMLElement();
1129 return rc;
1132 /* XSecuritySAXEventKeeper */
1133 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1134 cssxc::sax::ElementMarkPriority priority,
1135 sal_Bool modifyElement )
1136 throw (cssu::RuntimeException)
1138 return createElementCollector(
1139 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1140 priority,
1141 modifyElement,
1142 NULL);
1145 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1146 sal_Int32 referenceId,
1147 cssxc::sax::ElementMarkPriority priority )
1148 throw (cssu::RuntimeException)
1150 sal_Int32 nId = -1;
1152 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1153 if (pElementCollector != NULL)
1155 nId = m_nNextElementMarkId;
1156 m_nNextElementMarkId ++;
1158 ElementCollector* pClonedOne
1159 = pElementCollector->clone(nId, priority);
1162 * add this EC into the security data buffer array.
1164 m_vElementMarkBuffers.push_back(pClonedOne);
1167 * If the reference EC is still in initial EC array, add
1168 * this cloned one into the initial EC array too.
1170 if (pElementCollector->getBufferNode() == NULL)
1172 m_vNewElementCollectors.push_back(pClonedOne);
1176 return nId;
1179 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1180 throw (cssu::RuntimeException)
1182 ElementMark* pElementMark = findElementMarkBuffer(id);
1183 if (pElementMark != NULL)
1185 pElementMark->setSecurityId(securityId);
1190 /* XReferenceResolvedBroadcaster */
1191 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1192 sal_Int32 referenceId,
1193 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1194 throw (cssu::RuntimeException)
1196 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1197 if (pElementCollector != NULL)
1199 pElementCollector->setReferenceResolvedListener(listener);
1203 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1204 sal_Int32 /*referenceId*/,
1205 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1206 throw (cssu::RuntimeException)
1210 /* XSAXEventKeeperStatusChangeBroadcaster */
1211 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1212 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1213 throw (cssu::RuntimeException)
1215 m_xSAXEventKeeperStatusChangeListener = listener;
1218 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1219 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1220 throw (cssu::RuntimeException)
1224 /* XDocumentHandler */
1225 void SAL_CALL SAXEventKeeperImpl::startDocument( )
1226 throw (cssxs::SAXException, cssu::RuntimeException)
1228 if ( m_xNextHandler.is())
1230 m_xNextHandler->startDocument();
1234 void SAL_CALL SAXEventKeeperImpl::endDocument( )
1235 throw (cssxs::SAXException, cssu::RuntimeException)
1237 if ( m_xNextHandler.is())
1239 m_xNextHandler->endDocument();
1243 void SAL_CALL SAXEventKeeperImpl::startElement(
1244 const rtl::OUString& aName,
1245 const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1246 throw (cssxs::SAXException, cssu::RuntimeException)
1249 * If there is a following handler and no blocking now, then
1250 * forward this event
1252 if ((m_pCurrentBlockingBufferNode == NULL) &&
1253 (m_xNextHandler.is()) &&
1254 (!m_bIsForwarding) &&
1255 (m_pNewBlocker == NULL))
1257 m_xNextHandler->startElement(aName, xAttribs);
1261 * If not forwarding, buffer this startElement.
1263 if (!m_bIsForwarding)
1265 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1266 m_xDocumentHandler->startElement(aName, xAttribs);
1267 #else
1268 sal_Int32 nLength = xAttribs->getLength();
1269 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1271 for ( int i = 0; i<nLength; ++i )
1273 aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1274 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1277 m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
1278 #endif
1282 BufferNode* pBufferNode = addNewElementMarkBuffers();
1283 if (pBufferNode != NULL)
1285 setCurrentBufferNode(pBufferNode);
1289 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
1290 throw (cssxs::SAXException, cssu::RuntimeException)
1292 sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1295 * If there is a following handler and no blocking now, then
1296 * forward this event
1298 if ((m_pCurrentBlockingBufferNode == NULL) &&
1299 (m_xNextHandler.is()) &&
1300 (!m_bIsForwarding))
1302 m_xNextHandler->endElement(aName);
1305 if ((m_pCurrentBlockingBufferNode != NULL) ||
1306 (m_pCurrentBufferNode != m_pRootBufferNode) ||
1307 (!m_xXMLDocument->isCurrentElementEmpty()))
1309 if (!m_bIsForwarding)
1311 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1312 m_xDocumentHandler->endElement(aName);
1313 #else
1314 m_xCompressedDocumentHandler->_endElement(aName);
1315 #endif
1319 * If the current buffer node has not notified yet, and
1320 * the current buffer node is waiting for the current element,
1321 * then let it notify.
1323 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1325 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1326 m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
1328 pOldCurrentBufferNode->setReceivedAll();
1330 if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1331 m_xSAXEventKeeperStatusChangeListener.is())
1333 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1337 else
1339 if (!m_bIsForwarding)
1341 m_xXMLDocument->removeCurrentElement();
1346 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
1347 throw (cssxs::SAXException, cssu::RuntimeException)
1349 if (!m_bIsForwarding)
1351 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1353 m_xNextHandler->characters(aChars);
1356 if ((m_pCurrentBlockingBufferNode != NULL) ||
1357 (m_pCurrentBufferNode != m_pRootBufferNode))
1359 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1360 m_xDocumentHandler->characters(aChars);
1361 #else
1362 m_xCompressedDocumentHandler->_characters(aChars);
1363 #endif
1368 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1369 throw (cssxs::SAXException, cssu::RuntimeException)
1371 characters( aWhitespaces );
1374 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1375 const rtl::OUString& aTarget, const rtl::OUString& aData )
1376 throw (cssxs::SAXException, cssu::RuntimeException)
1378 if (!m_bIsForwarding)
1380 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1382 m_xNextHandler->processingInstruction(aTarget, aData);
1385 if ((m_pCurrentBlockingBufferNode != NULL) ||
1386 (m_pCurrentBufferNode != m_pRootBufferNode))
1388 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1389 m_xDocumentHandler->processingInstruction(aTarget, aData);
1390 #else
1391 m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
1392 #endif
1397 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1398 throw (cssxs::SAXException, cssu::RuntimeException)
1402 /* XInitialization */
1403 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1404 throw (cssu::Exception, cssu::RuntimeException)
1406 OSL_ASSERT(aArguments.getLength() == 1);
1408 aArguments[0] >>= m_xXMLDocument;
1409 m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1410 m_xXMLDocument, cssu::UNO_QUERY );
1411 m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1412 m_xXMLDocument, cssu::UNO_QUERY );
1414 m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1415 m_pCurrentBufferNode = m_pRootBufferNode;
1418 rtl::OUString SAXEventKeeperImpl_getImplementationName ()
1419 throw (cssu::RuntimeException)
1421 return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1424 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
1425 throw (cssu::RuntimeException)
1427 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1430 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( )
1431 throw (cssu::RuntimeException)
1433 cssu::Sequence < rtl::OUString > aRet(1);
1434 rtl::OUString* pArray = aRet.getArray();
1435 pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1436 return aRet;
1438 #undef SERVICE_NAME
1440 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1441 const cssu::Reference< cssl::XMultiServiceFactory > &)
1442 throw( cssu::Exception )
1444 return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1447 /* XServiceInfo */
1448 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1449 throw (cssu::RuntimeException)
1451 return SAXEventKeeperImpl_getImplementationName();
1453 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
1454 throw (cssu::RuntimeException)
1456 return SAXEventKeeperImpl_supportsService( rServiceName );
1458 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1459 throw (cssu::RuntimeException)
1461 return SAXEventKeeperImpl_getSupportedServiceNames();