Update ooo320-m1
[ooovba.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blob032515723cbcfb1eefb36ba1b2095fa4cff7fc9d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: saxeventkeeperimpl.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmlsecurity.hxx"
34 #include "saxeventkeeperimpl.hxx"
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
37 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
39 namespace cssu = com::sun::star::uno;
40 namespace cssl = com::sun::star::lang;
41 namespace cssxc = com::sun::star::xml::crypto;
42 namespace cssxcsax = com::sun::star::xml::csax;
43 namespace cssxw = com::sun::star::xml::wrapper;
44 namespace cssxs = com::sun::star::xml::sax;
46 #define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
47 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
49 #define _USECOMPRESSEDDOCUMENTHANDLER
51 SAXEventKeeperImpl::SAXEventKeeperImpl( )
52 :m_pRootBufferNode(NULL),
53 m_pCurrentBufferNode(NULL),
54 m_nNextElementMarkId(1),
55 m_pNewBlocker(NULL),
56 m_pCurrentBlockingBufferNode(NULL),
57 m_bIsReleasing(false),
58 m_bIsForwarding(false)
60 m_vElementMarkBuffers.reserve(2);
61 m_vNewElementCollectors.reserve(2);
62 m_vReleasedElementMarkBuffers.reserve(2);
65 SAXEventKeeperImpl::~SAXEventKeeperImpl()
68 * delete the BufferNode tree
70 if (m_pRootBufferNode != NULL)
72 m_pRootBufferNode->freeAllChildren();
73 delete m_pRootBufferNode;
76 m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
79 * delete all unfreed ElementMarks
81 m_vNewElementCollectors.clear();
82 m_pNewBlocker = NULL;
84 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
85 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
87 delete (*ii);
89 m_vElementMarkBuffers.clear();
92 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
93 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
95 * NAME
96 * setCurrentBufferNode -- set a new active BufferNode.
98 * SYNOPSIS
99 * setCurrentBufferNode( pBufferNode );
101 * FUNCTION
102 * connects this BufferNode into the BufferNode tree as a child of the
103 * current active BufferNode. Then makes this BufferNode as the current
104 * active BufferNode.
105 * If the previous active BufferNode points to the root
106 * BufferNode, which means that no buffering operation was proceeding,
107 * then notifies the status change listener that buffering operation
108 * will begin at once.
110 * INPUTS
111 * pBufferNode - a BufferNode which will be the new active BufferNode
113 * RESULT
114 * empty
116 * HISTORY
117 * 05.01.2004 - implemented
119 * AUTHOR
120 * Michael Mi
121 * Email: michael.mi@sun.com
122 ******************************************************************************/
124 if (pBufferNode != m_pCurrentBufferNode)
126 if ( m_pCurrentBufferNode == m_pRootBufferNode &&
127 m_xSAXEventKeeperStatusChangeListener.is())
129 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
132 if (pBufferNode->getParent() == NULL)
134 m_pCurrentBufferNode->addChild(pBufferNode);
135 pBufferNode->setParent(m_pCurrentBufferNode);
138 m_pCurrentBufferNode = pBufferNode;
142 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
143 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
145 * NAME
146 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
148 * SYNOPSIS
149 * pBufferNode = addNewElementMarkBuffers( );
151 * FUNCTION
152 * if there are new ElementCollector or new Blocker to be added, then
153 * connect all of them with the current BufferNode. In case of the
154 * current BufferNode doesn't exist, creates one.
155 * Clears up the new ElementCollector list and the new Blocker pointer.
157 * INPUTS
158 * empty
160 * RESULT
161 * pBufferNode - the BufferNode that has been connected with both new
162 * ElementCollectors and new Blocker.
164 * HISTORY
165 * 05.01.2004 - implemented
167 * AUTHOR
168 * Michael Mi
169 * Email: michael.mi@sun.com
170 ******************************************************************************/
172 BufferNode* pBufferNode = NULL;
174 if ( (m_vNewElementCollectors.size()>0) ||
175 (m_pNewBlocker != NULL))
178 * When the current BufferNode is right pointing to the current
179 * working element in the XMLDocumentWrapper component, then
180 * no new BufferNode is needed to create.
181 * This situation can only happen in the "Forwarding" mode.
183 if ( (m_pCurrentBufferNode != NULL) &&
184 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
186 pBufferNode = m_pCurrentBufferNode;
188 else
190 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
193 if (m_pNewBlocker != NULL)
195 pBufferNode->setBlocker(m_pNewBlocker);
198 * If no blocking before, then notify the status change listener that
199 * the SAXEventKeeper has entered "blocking" status, during which, no
200 * SAX events will be forwarded to the next document handler.
202 if (m_pCurrentBlockingBufferNode == NULL)
204 m_pCurrentBlockingBufferNode = pBufferNode;
206 if (m_xSAXEventKeeperStatusChangeListener.is())
208 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
212 m_pNewBlocker = NULL;
215 if (m_vNewElementCollectors.size()>0)
217 std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
219 for( ; ii != m_vNewElementCollectors.end(); ++ii )
221 pBufferNode->addElementCollector(*ii);
224 m_vNewElementCollectors.clear();
228 return pBufferNode;
231 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
232 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
234 * NAME
235 * findElementMarkBuffer -- finds an ElementMark.
237 * SYNOPSIS
238 * pElementMark = findElementMarkBuffer( nId );
240 * FUNCTION
241 * searches an ElementMark with the particular Id in the ElementMark
242 * list.
244 * INPUTS
245 * nId - the Id of the ElementMark to be searched.
247 * RESULT
248 * pElementMark - the ElementMark with the particular Id, or NULL when
249 * no such Id exists.
251 * HISTORY
252 * 05.01.2004 - implemented
254 * AUTHOR
255 * Michael Mi
256 * Email: michael.mi@sun.com
257 ******************************************************************************/
259 ElementMark* pElementMark = NULL;
261 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
263 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
265 if ( nId == (*ii)->getBufferId())
267 pElementMark = (ElementMark*)*ii;
268 break;
272 return pElementMark;
275 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
276 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
278 * NAME
279 * removeElementMarkBuffer -- removes an ElementMark
281 * SYNOPSIS
282 * removeElementMarkBuffer( nId );
284 * FUNCTION
285 * removes an ElementMark with the particular Id in the ElementMark list.
287 * INPUTS
288 * nId - the Id of the ElementMark to be removed.
290 * RESULT
291 * empty
293 * HISTORY
294 * 05.01.2004 - implemented
296 * AUTHOR
297 * Michael Mi
298 * Email: michael.mi@sun.com
299 ******************************************************************************/
301 std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
303 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
305 if ( nId == (*ii)->getBufferId())
308 * checks whether this ElementMark still in the new ElementCollect array
310 std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
311 for( ; jj != m_vNewElementCollectors.end(); ++jj )
313 if ((*ii) == (*jj))
315 m_vNewElementCollectors.erase(jj);
316 break;
321 * checks whether this ElementMark is the new Blocker
323 if ((*ii) == m_pNewBlocker)
325 m_pNewBlocker = NULL;
329 * destory the ElementMark
331 delete (*ii);
333 m_vElementMarkBuffers.erase( ii );
334 break;
339 rtl::OUString SAXEventKeeperImpl::printBufferNode(
340 BufferNode* pBufferNode, sal_Int32 nIndent) const
341 /****** SAXEventKeeperImpl/printBufferNode ***********************************
343 * NAME
344 * printBufferNode -- retrieves the information of a BufferNode and its
345 * branch.
347 * SYNOPSIS
348 * info = printBufferNode( pBufferNode, nIndent );
350 * FUNCTION
351 * all retrieved information includes:
352 * 1. whether it is the current BufferNode;
353 * 2. whether it is the current blocking BufferNode;
354 * 3. the name of the parent element;
355 * 4. the name of this element;
356 * 5. all ElementCollectors working on this BufferNode;
357 * 6. the Blocker working on this BufferNode;
358 * 7. all child BufferNodes' information.
360 * INPUTS
361 * pBufferNode - the BufferNode from where information will be retrieved.
362 * nIndent - how many space characters prefixed before the output
363 * message.
365 * RESULT
366 * info - the information string
368 * HISTORY
369 * 05.01.2004 - implemented
371 * AUTHOR
372 * Michael Mi
373 * Email: michael.mi@sun.com
374 ******************************************************************************/
376 rtl::OUString rc;
378 for ( int i=0; i<nIndent; ++i )
380 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
383 if (pBufferNode == m_pCurrentBufferNode)
385 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
388 if (pBufferNode == m_pCurrentBlockingBufferNode)
390 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
393 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
394 rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
396 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
397 if (pParent != NULL)
399 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
400 rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
401 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
404 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
405 rc += pBufferNode->printChildren();
406 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));
408 ElementMark * pBlocker = pBufferNode->getBlocker();
409 if (pBlocker != NULL)
411 rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
412 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
413 rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
414 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
415 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
417 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
419 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
420 std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
421 for( ; jj != vChildren->end(); ++jj )
423 rc += printBufferNode((BufferNode *)*jj, nIndent+4);
426 delete vChildren;
428 return rc;
431 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
432 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
433 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
435 * NAME
436 * collectChildWorkingElement -- collects a BufferNode's all child
437 * Elements.
439 * SYNOPSIS
440 * list = collectChildWorkingElement( pBufferNode );
442 * FUNCTION
443 * see NAME.
445 * INPUTS
446 * pBufferNode - the BufferNode whose child Elements will be collected.
448 * RESULT
449 * list - the child Elements list.
451 * HISTORY
452 * 05.01.2004 - implemented
454 * AUTHOR
455 * Michael Mi
456 * Email: michael.mi@sun.com
457 ******************************************************************************/
459 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
461 cssu::Sequence < cssu::Reference<
462 cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
464 std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
466 sal_Int32 nIndex = 0;
467 for( ; ii != vChildren->end(); ++ii )
469 aChildrenCollection[nIndex] = (*ii)->getXMLElement();
470 nIndex++;
473 delete vChildren;
475 return aChildrenCollection;
478 void SAXEventKeeperImpl::smashBufferNode(
479 BufferNode* pBufferNode, bool bClearRoot) const
480 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
482 * NAME
483 * smashBufferNode -- removes a BufferNode along with its working
484 * element.
486 * SYNOPSIS
487 * smashBufferNode( pBufferNode, bClearRoot );
489 * FUNCTION
490 * removes the BufferNode's working element from the DOM document, while
491 * reserves all ancestor paths for its child BufferNodes.
492 * when any of the BufferNode's ancestor element is useless, removes it
493 * too.
494 * removes the BufferNode from the BufferNode tree.
496 * INPUTS
497 * pBufferNode - the BufferNode to be removed
498 * bClearRoot - whether the root element also needs to be cleared up.
500 * RESULT
501 * empty
503 * NOTES
504 * when removeing a Blocker's BufferNode, the bClearRoot flag should be
505 * true. Because a Blocker can buffer many SAX events which are not used
506 * by any other ElementCollector or Blocker.
507 * When the bClearRoot is set to true, the root BufferNode will be first
508 * cleared, with a stop flag seting at the next Blocking BufferNode. This
509 * operation can delete all useless bufferred SAX events which are only
510 * needed by the Blocker to be deleted.
512 * HISTORY
513 * 05.01.2004 - implemented
515 * AUTHOR
516 * Michael Mi
517 * Email: michael.mi@sun.com
518 ******************************************************************************/
520 if (!pBufferNode->hasAnything())
522 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
525 * delete the XML data
527 if (pParent == m_pRootBufferNode)
529 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
530 bool bIsBlockInside = false;
531 bool bIsBlockingAfterward = false;
534 * If this is a blocker, then remove any out-element data
535 * which caused by blocking. The removal process will stop
536 * at the next blokcer to avoid removing any useful data.
538 if (bClearRoot)
540 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
541 aChildElements = collectChildWorkingElement(m_pRootBufferNode);
544 * the clearUselessData only clearup the content in the
545 * node, not the node itself.
547 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
548 aChildElements,
549 bIsNotBlocking?(NULL):
550 (m_pCurrentBlockingBufferNode->getXMLElement()));
553 * remove the node if it is empty, then if its parent is also
554 * empty, remove it, then if the next parent is also empty,
555 * remove it,..., until parent become null.
557 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
561 * if blocking, check the relationship between this BufferNode and
562 * the current blocking BufferNode.
564 if ( !bIsNotBlocking )
567 * the current blocking BufferNode is a descendant of this BufferNode.
569 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
572 * the current blocking BufferNode locates behind this BufferNode in tree
573 * order.
575 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
579 * this BufferNode's working element needs to be deleted only when
580 * 1. there is no blocking, or
581 * 2. the current blocking BufferNode is a descendant of this BufferNode,
582 * (then in the BufferNode's working element, the useless data before the blocking
583 * element should be deleted.) or
584 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
585 * (then the useless data between the blocking element and the working element
586 * should be deleted.).
587 * Otherwise, this working element should not be deleted.
589 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
591 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
592 aChildElements = collectChildWorkingElement(pBufferNode);
595 * the clearUselessData only clearup the content in the
596 * node, not the node itself.
598 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
599 aChildElements,
600 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
601 (NULL));
604 * remove the node if it is empty, then if its parent is also
605 * empty, remove it, then if the next parent is also empty,
606 * remove it,..., until parent become null.
608 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
612 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
614 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
615 pParent->removeChild(pBufferNode);
616 pBufferNode->setParent(NULL);
618 std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
619 for( ; ii != vChildren->end(); ++ii )
621 ((BufferNode *)(*ii))->setParent(pParent);
622 pParent->addChild(*ii, nIndex);
623 nIndex++;
626 delete vChildren;
629 * delete the BufferNode
631 delete pBufferNode;
635 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
636 BufferNode* pStartBufferNode) const
637 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
639 * NAME
640 * findNextBlockingBufferNode -- finds the next blocking BufferNode
641 * behind the particular BufferNode.
643 * SYNOPSIS
644 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
646 * FUNCTION
647 * see NAME.
649 * INPUTS
650 * pStartBufferNode - the BufferNode from where to search the next
651 * blocking BufferNode.
653 * RESULT
654 * pBufferNode - the next blocking BufferNode, or NULL if no such
655 * BufferNode exists.
657 * HISTORY
658 * 05.01.2004 - implemented
660 * AUTHOR
661 * Michael Mi
662 * Email: michael.mi@sun.com
663 ******************************************************************************/
665 BufferNode* pNext = NULL;
667 if (pStartBufferNode != NULL)
669 pNext = pStartBufferNode;
671 while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
673 if (pNext->getBlocker() != NULL)
675 break;
680 return pNext;
683 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
684 /****** SAXEventKeeperImpl/diffuse *******************************************
686 * NAME
687 * diffuse -- diffuse the notification.
689 * SYNOPSIS
690 * diffuse( pBufferNode );
692 * FUNCTION
693 * diffuse the collecting completion notification from the specific
694 * BufferNode along its parent link, until an ancestor which is not
695 * completely received is met.
697 * INPUTS
698 * pBufferNode - the BufferNode from which the notification will be
699 * diffused.
701 * RESULT
702 * empty
704 * HISTORY
705 * 05.01.2004 - implemented
707 * AUTHOR
708 * Michael Mi
709 * Email: michael.mi@sun.com
710 ******************************************************************************/
712 BufferNode* pParent = pBufferNode;
714 while(pParent->isAllReceived())
716 pParent->elementCollectorNotify();
717 pParent = (BufferNode*)pParent->getParent();
721 void SAXEventKeeperImpl::releaseElementMarkBuffer()
722 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
724 * NAME
725 * releaseElementMarkBuffer -- releases useless ElementMarks
727 * SYNOPSIS
728 * releaseElementMarkBuffer( );
730 * FUNCTION
731 * releases each ElementMark in the releasing list
732 * m_vReleasedElementMarkBuffers.
733 * The operation differs between an ElementCollector and a Blocker.
735 * INPUTS
736 * empty
738 * RESULT
739 * empty
741 * HISTORY
742 * 05.01.2004 - implemented
744 * AUTHOR
745 * Michael Mi
746 * Email: michael.mi@sun.com
747 ******************************************************************************/
749 m_bIsReleasing = true;
750 while (m_vReleasedElementMarkBuffers.size()>0)
752 std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
753 sal_Int32 nId = *pId;
754 m_vReleasedElementMarkBuffers.erase( pId );
756 ElementMark* pElementMark = findElementMarkBuffer(nId);
758 if (pElementMark != NULL)
760 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
761 == pElementMark->getType())
763 * it is a EC
766 ElementCollector* pElementCollector = (ElementCollector*)pElementMark;
768 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
769 bool bToModify = pElementCollector->getModify();
772 * Delete the EC from the buffer node.
774 BufferNode* pBufferNode = pElementCollector->getBufferNode();
775 pBufferNode->removeElementCollector(pElementCollector);
777 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
779 pBufferNode->notifyBranch();
782 if (bToModify)
784 pBufferNode->notifyAncestor();
788 * delete the ElementMark
790 pElementCollector = NULL;
791 pElementMark = NULL;
792 removeElementMarkBuffer(nId);
795 * delete the BufferNode
797 diffuse(pBufferNode);
798 smashBufferNode(pBufferNode, false);
800 else
802 * it is a Blocker
806 * Delete the TH from the buffer node.
808 BufferNode *pBufferNode = pElementMark->getBufferNode();
809 pBufferNode->setBlocker(NULL);
812 * If there is a following handler and no blocking now, then
813 * forward this event
815 if (m_pCurrentBlockingBufferNode == pBufferNode)
818 * Before forwarding, the next blocking point needs to be
819 * found.
821 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
824 * Forward the blocked events between these two STHs.
826 if (m_xNextHandler.is())
828 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
829 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
831 m_pCurrentBufferNode = pBufferNode;
832 m_pCurrentBlockingBufferNode = NULL;
834 m_bIsForwarding = true;
836 m_xXMLDocument->generateSAXEvents(
837 m_xNextHandler,
838 this,
839 pBufferNode->getXMLElement(),
840 (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
842 m_bIsForwarding = false;
844 m_pCurrentBufferNode = pTempCurrentBufferNode;
845 if (m_pCurrentBlockingBufferNode == NULL)
847 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
851 if (m_pCurrentBlockingBufferNode == NULL &&
852 m_xSAXEventKeeperStatusChangeListener.is())
854 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
859 * delete the ElementMark
861 pElementMark = NULL;
862 removeElementMarkBuffer(nId);
865 * delete the BufferNode
867 diffuse(pBufferNode);
868 smashBufferNode(pBufferNode, true);
873 m_bIsReleasing = false;
875 if (!m_pRootBufferNode->hasAnything() &&
876 !m_pRootBufferNode->hasChildren() &&
877 m_xSAXEventKeeperStatusChangeListener.is())
879 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
883 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
884 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
886 * NAME
887 * markElementMarkBuffer -- marks an ElementMark to be released
889 * SYNOPSIS
890 * markElementMarkBuffer( nId );
892 * FUNCTION
893 * puts the ElementMark with the particular Id into the releasing list,
894 * checks whether the releasing process is runing, if not then launch
895 * this process.
897 * INPUTS
898 * nId - the Id of the ElementMark which will be released
900 * RESULT
901 * empty
903 * HISTORY
904 * 05.01.2004 - implemented
906 * AUTHOR
907 * Michael Mi
908 * Email: michael.mi@sun.com
909 ******************************************************************************/
911 m_vReleasedElementMarkBuffers.push_back( nId );
912 if ( !m_bIsReleasing )
914 releaseElementMarkBuffer();
918 sal_Int32 SAXEventKeeperImpl::createElementCollector(
919 sal_Int32 nSecurityId,
920 cssxc::sax::ElementMarkPriority nPriority,
921 bool bModifyElement,
922 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
923 /****** SAXEventKeeperImpl/createElementCollector ****************************
925 * NAME
926 * createElementCollector -- creates a new ElementCollector on the
927 * incoming element.
929 * SYNOPSIS
930 * nId = createElementCollector( nSecurityId, nPriority,
931 * bModifyElement,
932 * xReferenceResolvedListener );
934 * FUNCTION
935 * allocs a new Id, then create an ElementCollector with this Id value.
936 * Add the new created ElementCollector to the new ElementCollecotor list.
938 * INPUTS
939 * nSecurityId - the security Id of the new ElementCollector
940 * nPriority - the prirority of the new ElementCollector
941 * bModifyElement -whether this BufferNode will modify the content of
942 * the corresponding element it works on
943 * xReferenceResolvedListener - the listener for the new ElementCollector.
945 * RESULT
946 * nId - the Id of the new ElementCollector
948 * HISTORY
949 * 05.01.2004 - implemented
951 * AUTHOR
952 * Michael Mi
953 * Email: michael.mi@sun.com
954 ******************************************************************************/
956 sal_Int32 nId = m_nNextElementMarkId;
957 m_nNextElementMarkId ++;
959 ElementCollector* pElementCollector
960 = new ElementCollector(
961 nSecurityId,
962 nId,
963 nPriority,
964 bModifyElement,
965 xReferenceResolvedListener);
967 m_vElementMarkBuffers.push_back( pElementCollector );
970 * All the new EC to initial EC array.
972 m_vNewElementCollectors.push_back( pElementCollector );
974 return nId;
978 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
979 /****** SAXEventKeeperImpl/createBlocker *************************************
981 * NAME
982 * createBlocker -- creates a new Blocker on the incoming element.
984 * SYNOPSIS
985 * nId = createBlocker( nSecurityId );
987 * FUNCTION
988 * see NAME.
990 * INPUTS
991 * nSecurityId - the security Id of the new Blocker
993 * RESULT
994 * nId - the Id of the new Blocker
996 * HISTORY
997 * 05.01.2004 - implemented
999 * AUTHOR
1000 * Michael Mi
1001 * Email: michael.mi@sun.com
1002 ******************************************************************************/
1004 sal_Int32 nId = m_nNextElementMarkId;
1005 m_nNextElementMarkId ++;
1007 OSL_ASSERT(m_pNewBlocker == NULL);
1009 m_pNewBlocker = new ElementMark(nSecurityId, nId);
1010 m_vElementMarkBuffers.push_back( m_pNewBlocker );
1012 return nId;
1015 /* XSAXEventKeeper */
1016 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
1017 throw (cssu::RuntimeException)
1019 return createElementCollector(
1020 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1021 cssxc::sax::ElementMarkPriority_AFTERMODIFY,
1022 false,
1023 NULL);
1026 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
1027 throw (cssu::RuntimeException)
1029 markElementMarkBuffer(id);
1032 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
1033 throw (cssu::RuntimeException)
1035 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
1038 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
1039 throw (cssu::RuntimeException)
1041 markElementMarkBuffer(id);
1044 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
1045 throw (cssu::RuntimeException)
1047 return (m_pCurrentBlockingBufferNode != NULL);
1050 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
1051 SAXEventKeeperImpl::getElement( sal_Int32 id )
1052 throw (cssu::RuntimeException)
1054 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1056 ElementMark* pElementMark = findElementMarkBuffer(id);
1057 if (pElementMark != NULL)
1059 rc = pElementMark->getBufferNode()->getXMLElement();
1062 return rc;
1065 void SAL_CALL SAXEventKeeperImpl::setElement(
1066 sal_Int32 id,
1067 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1068 throw (cssu::RuntimeException)
1070 if (aElement.is())
1072 m_xXMLDocument->rebuildIDLink(aElement);
1074 ElementMark* pElementMark = findElementMarkBuffer(id);
1076 if (pElementMark != NULL)
1078 BufferNode* pBufferNode = pElementMark->getBufferNode();
1079 if (pBufferNode != NULL)
1081 bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1082 pBufferNode->setXMLElement(aElement);
1084 if (bIsCurrent)
1086 m_xXMLDocument->setCurrentElement(aElement);
1091 else
1093 removeElementCollector( id );
1097 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1098 const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1099 throw (cssu::RuntimeException)
1101 cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1103 m_xNextHandler = xNewHandler;
1104 return xOldHandler;
1107 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1108 throw (cssu::RuntimeException)
1110 rtl::OUString rc;
1112 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
1113 rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
1114 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
1115 rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1116 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
1117 rc += printBufferNode(m_pRootBufferNode, 0);
1119 return rc;
1122 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1123 throw (cssu::RuntimeException)
1125 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1127 if (m_pCurrentBlockingBufferNode != NULL)
1129 rc = m_pCurrentBlockingBufferNode->getXMLElement();
1132 return rc;
1135 /* XSecuritySAXEventKeeper */
1136 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1137 cssxc::sax::ElementMarkPriority priority,
1138 sal_Bool modifyElement )
1139 throw (cssu::RuntimeException)
1141 return createElementCollector(
1142 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1143 priority,
1144 modifyElement,
1145 NULL);
1148 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1149 sal_Int32 referenceId,
1150 cssxc::sax::ElementMarkPriority priority )
1151 throw (cssu::RuntimeException)
1153 sal_Int32 nId = -1;
1155 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1156 if (pElementCollector != NULL)
1158 nId = m_nNextElementMarkId;
1159 m_nNextElementMarkId ++;
1161 ElementCollector* pClonedOne
1162 = pElementCollector->clone(nId, priority);
1165 * add this EC into the security data buffer array.
1167 m_vElementMarkBuffers.push_back(pClonedOne);
1170 * If the reference EC is still in initial EC array, add
1171 * this cloned one into the initial EC array too.
1173 if (pElementCollector->getBufferNode() == NULL)
1175 m_vNewElementCollectors.push_back(pClonedOne);
1179 return nId;
1182 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1183 throw (cssu::RuntimeException)
1185 ElementMark* pElementMark = findElementMarkBuffer(id);
1186 if (pElementMark != NULL)
1188 pElementMark->setSecurityId(securityId);
1193 /* XReferenceResolvedBroadcaster */
1194 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1195 sal_Int32 referenceId,
1196 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1197 throw (cssu::RuntimeException)
1199 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1200 if (pElementCollector != NULL)
1202 pElementCollector->setReferenceResolvedListener(listener);
1206 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1207 sal_Int32 /*referenceId*/,
1208 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1209 throw (cssu::RuntimeException)
1213 /* XSAXEventKeeperStatusChangeBroadcaster */
1214 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1215 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1216 throw (cssu::RuntimeException)
1218 m_xSAXEventKeeperStatusChangeListener = listener;
1221 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1222 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1223 throw (cssu::RuntimeException)
1227 /* XDocumentHandler */
1228 void SAL_CALL SAXEventKeeperImpl::startDocument( )
1229 throw (cssxs::SAXException, cssu::RuntimeException)
1231 if ( m_xNextHandler.is())
1233 m_xNextHandler->startDocument();
1237 void SAL_CALL SAXEventKeeperImpl::endDocument( )
1238 throw (cssxs::SAXException, cssu::RuntimeException)
1240 if ( m_xNextHandler.is())
1242 m_xNextHandler->endDocument();
1246 void SAL_CALL SAXEventKeeperImpl::startElement(
1247 const rtl::OUString& aName,
1248 const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1249 throw (cssxs::SAXException, cssu::RuntimeException)
1252 * If there is a following handler and no blocking now, then
1253 * forward this event
1255 if ((m_pCurrentBlockingBufferNode == NULL) &&
1256 (m_xNextHandler.is()) &&
1257 (!m_bIsForwarding) &&
1258 (m_pNewBlocker == NULL))
1260 m_xNextHandler->startElement(aName, xAttribs);
1264 * If not forwarding, buffer this startElement.
1266 if (!m_bIsForwarding)
1268 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1269 m_xDocumentHandler->startElement(aName, xAttribs);
1270 #else
1271 sal_Int32 nLength = xAttribs->getLength();
1272 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1274 for ( int i = 0; i<nLength; ++i )
1276 aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1277 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1280 m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
1281 #endif
1285 BufferNode* pBufferNode = addNewElementMarkBuffers();
1286 if (pBufferNode != NULL)
1288 setCurrentBufferNode(pBufferNode);
1292 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
1293 throw (cssxs::SAXException, cssu::RuntimeException)
1295 sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1298 * If there is a following handler and no blocking now, then
1299 * forward this event
1301 if ((m_pCurrentBlockingBufferNode == NULL) &&
1302 (m_xNextHandler.is()) &&
1303 (!m_bIsForwarding))
1305 m_xNextHandler->endElement(aName);
1308 if ((m_pCurrentBlockingBufferNode != NULL) ||
1309 (m_pCurrentBufferNode != m_pRootBufferNode) ||
1310 (!m_xXMLDocument->isCurrentElementEmpty()))
1312 if (!m_bIsForwarding)
1314 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1315 m_xDocumentHandler->endElement(aName);
1316 #else
1317 m_xCompressedDocumentHandler->_endElement(aName);
1318 #endif
1322 * If the current buffer node has not notified yet, and
1323 * the current buffer node is waiting for the current element,
1324 * then let it notify.
1326 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1328 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1329 m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
1331 pOldCurrentBufferNode->setReceivedAll();
1333 if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1334 m_xSAXEventKeeperStatusChangeListener.is())
1336 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1340 else
1342 if (!m_bIsForwarding)
1344 m_xXMLDocument->removeCurrentElement();
1349 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
1350 throw (cssxs::SAXException, cssu::RuntimeException)
1352 if (!m_bIsForwarding)
1354 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1356 m_xNextHandler->characters(aChars);
1359 if ((m_pCurrentBlockingBufferNode != NULL) ||
1360 (m_pCurrentBufferNode != m_pRootBufferNode))
1362 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1363 m_xDocumentHandler->characters(aChars);
1364 #else
1365 m_xCompressedDocumentHandler->_characters(aChars);
1366 #endif
1371 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1372 throw (cssxs::SAXException, cssu::RuntimeException)
1374 characters( aWhitespaces );
1377 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1378 const rtl::OUString& aTarget, const rtl::OUString& aData )
1379 throw (cssxs::SAXException, cssu::RuntimeException)
1381 if (!m_bIsForwarding)
1383 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1385 m_xNextHandler->processingInstruction(aTarget, aData);
1388 if ((m_pCurrentBlockingBufferNode != NULL) ||
1389 (m_pCurrentBufferNode != m_pRootBufferNode))
1391 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1392 m_xDocumentHandler->processingInstruction(aTarget, aData);
1393 #else
1394 m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
1395 #endif
1400 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1401 throw (cssxs::SAXException, cssu::RuntimeException)
1405 /* XInitialization */
1406 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1407 throw (cssu::Exception, cssu::RuntimeException)
1409 OSL_ASSERT(aArguments.getLength() == 1);
1411 aArguments[0] >>= m_xXMLDocument;
1412 m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1413 m_xXMLDocument, cssu::UNO_QUERY );
1414 m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1415 m_xXMLDocument, cssu::UNO_QUERY );
1417 m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1418 m_pCurrentBufferNode = m_pRootBufferNode;
1421 rtl::OUString SAXEventKeeperImpl_getImplementationName ()
1422 throw (cssu::RuntimeException)
1424 return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1427 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
1428 throw (cssu::RuntimeException)
1430 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1433 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( )
1434 throw (cssu::RuntimeException)
1436 cssu::Sequence < rtl::OUString > aRet(1);
1437 rtl::OUString* pArray = aRet.getArray();
1438 pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1439 return aRet;
1441 #undef SERVICE_NAME
1443 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1444 const cssu::Reference< cssl::XMultiServiceFactory > &)
1445 throw( cssu::Exception )
1447 return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1450 /* XServiceInfo */
1451 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1452 throw (cssu::RuntimeException)
1454 return SAXEventKeeperImpl_getImplementationName();
1456 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
1457 throw (cssu::RuntimeException)
1459 return SAXEventKeeperImpl_supportsService( rServiceName );
1461 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1462 throw (cssu::RuntimeException)
1464 return SAXEventKeeperImpl_getSupportedServiceNames();