Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / xmlsecurity / source / framework / saxeventkeeperimpl.cxx
blob54ed9152bbeee535332f84eacc5e0fcdd8160423
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>
26 namespace cssu = com::sun::star::uno;
27 namespace cssl = com::sun::star::lang;
28 namespace cssxc = com::sun::star::xml::crypto;
29 namespace cssxcsax = com::sun::star::xml::csax;
30 namespace cssxw = com::sun::star::xml::wrapper;
31 namespace cssxs = com::sun::star::xml::sax;
33 #define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
34 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
36 #define _USECOMPRESSEDDOCUMENTHANDLER
38 SAXEventKeeperImpl::SAXEventKeeperImpl( )
39 :m_pRootBufferNode(NULL),
40 m_pCurrentBufferNode(NULL),
41 m_nNextElementMarkId(1),
42 m_pNewBlocker(NULL),
43 m_pCurrentBlockingBufferNode(NULL),
44 m_bIsReleasing(false),
45 m_bIsForwarding(false)
47 m_vElementMarkBuffers.reserve(2);
48 m_vNewElementCollectors.reserve(2);
49 m_vReleasedElementMarkBuffers.reserve(2);
52 SAXEventKeeperImpl::~SAXEventKeeperImpl()
55 * delete the BufferNode tree
57 if (m_pRootBufferNode != NULL)
59 m_pRootBufferNode->freeAllChildren();
60 delete m_pRootBufferNode;
63 m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
66 * delete all unfreed ElementMarks
68 m_vNewElementCollectors.clear();
69 m_pNewBlocker = NULL;
71 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
72 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
74 delete (*ii);
76 m_vElementMarkBuffers.clear();
79 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
80 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
82 * NAME
83 * setCurrentBufferNode -- set a new active BufferNode.
85 * SYNOPSIS
86 * setCurrentBufferNode( pBufferNode );
88 * FUNCTION
89 * connects this BufferNode into the BufferNode tree as a child of the
90 * current active BufferNode. Then makes this BufferNode as the current
91 * active BufferNode.
92 * If the previous active BufferNode points to the root
93 * BufferNode, which means that no buffering operation was proceeding,
94 * then notifies the status change listener that buffering operation
95 * will begin at once.
97 * INPUTS
98 * pBufferNode - a BufferNode which will be the new active BufferNode
100 * RESULT
101 * empty
103 * AUTHOR
104 * Michael Mi
105 * Email: michael.mi@sun.com
106 ******************************************************************************/
108 if (pBufferNode != m_pCurrentBufferNode)
110 if ( m_pCurrentBufferNode == m_pRootBufferNode &&
111 m_xSAXEventKeeperStatusChangeListener.is())
113 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
116 if (pBufferNode->getParent() == NULL)
118 m_pCurrentBufferNode->addChild(pBufferNode);
119 pBufferNode->setParent(m_pCurrentBufferNode);
122 m_pCurrentBufferNode = pBufferNode;
126 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
127 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
129 * NAME
130 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
132 * SYNOPSIS
133 * pBufferNode = addNewElementMarkBuffers( );
135 * FUNCTION
136 * if there are new ElementCollector or new Blocker to be added, then
137 * connect all of them with the current BufferNode. In case of the
138 * current BufferNode doesn't exist, creates one.
139 * Clears up the new ElementCollector list and the new Blocker pointer.
141 * INPUTS
142 * empty
144 * RESULT
145 * pBufferNode - the BufferNode that has been connected with both new
146 * ElementCollectors and new Blocker.
148 * AUTHOR
149 * Michael Mi
150 * Email: michael.mi@sun.com
151 ******************************************************************************/
153 BufferNode* pBufferNode = NULL;
155 if (m_pNewBlocker || !m_vNewElementCollectors.empty() )
158 * When the current BufferNode is right pointing to the current
159 * working element in the XMLDocumentWrapper component, then
160 * no new BufferNode is needed to create.
161 * This situation can only happen in the "Forwarding" mode.
163 if ( (m_pCurrentBufferNode != NULL) &&
164 (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
166 pBufferNode = m_pCurrentBufferNode;
168 else
170 pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
173 if (m_pNewBlocker != NULL)
175 pBufferNode->setBlocker(m_pNewBlocker);
178 * If no blocking before, then notify the status change listener that
179 * the SAXEventKeeper has entered "blocking" status, during which, no
180 * SAX events will be forwarded to the next document handler.
182 if (m_pCurrentBlockingBufferNode == NULL)
184 m_pCurrentBlockingBufferNode = pBufferNode;
186 if (m_xSAXEventKeeperStatusChangeListener.is())
188 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
192 m_pNewBlocker = NULL;
195 if (!m_vNewElementCollectors.empty())
197 std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
199 for( ; ii != m_vNewElementCollectors.end(); ++ii )
201 pBufferNode->addElementCollector(*ii);
204 m_vNewElementCollectors.clear();
208 return pBufferNode;
211 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
212 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
214 * NAME
215 * findElementMarkBuffer -- finds an ElementMark.
217 * SYNOPSIS
218 * pElementMark = findElementMarkBuffer( nId );
220 * FUNCTION
221 * searches an ElementMark with the particular Id in the ElementMark
222 * list.
224 * INPUTS
225 * nId - the Id of the ElementMark to be searched.
227 * RESULT
228 * pElementMark - the ElementMark with the particular Id, or NULL when
229 * no such Id exists.
231 * AUTHOR
232 * Michael Mi
233 * Email: michael.mi@sun.com
234 ******************************************************************************/
236 ElementMark* pElementMark = NULL;
238 std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
240 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
242 if ( nId == (*ii)->getBufferId())
244 pElementMark = (ElementMark*)*ii;
245 break;
249 return pElementMark;
252 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
253 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
255 * NAME
256 * removeElementMarkBuffer -- removes an ElementMark
258 * SYNOPSIS
259 * removeElementMarkBuffer( nId );
261 * FUNCTION
262 * removes an ElementMark with the particular Id in the ElementMark list.
264 * INPUTS
265 * nId - the Id of the ElementMark to be removed.
267 * RESULT
268 * empty
270 * AUTHOR
271 * Michael Mi
272 * Email: michael.mi@sun.com
273 ******************************************************************************/
275 std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
277 for( ; ii != m_vElementMarkBuffers.end(); ++ii )
279 if ( nId == (*ii)->getBufferId())
282 * checks whether this ElementMark still in the new ElementCollect array
284 std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
285 for( ; jj != m_vNewElementCollectors.end(); ++jj )
287 if ((*ii) == (*jj))
289 m_vNewElementCollectors.erase(jj);
290 break;
295 * checks whether this ElementMark is the new Blocker
297 if ((*ii) == m_pNewBlocker)
299 m_pNewBlocker = NULL;
303 * destory the ElementMark
305 delete (*ii);
307 m_vElementMarkBuffers.erase( ii );
308 break;
313 rtl::OUString SAXEventKeeperImpl::printBufferNode(
314 BufferNode* pBufferNode, sal_Int32 nIndent) const
315 /****** SAXEventKeeperImpl/printBufferNode ***********************************
317 * NAME
318 * printBufferNode -- retrieves the information of a BufferNode and its
319 * branch.
321 * SYNOPSIS
322 * info = printBufferNode( pBufferNode, nIndent );
324 * FUNCTION
325 * all retrieved information includes:
326 * 1. whether it is the current BufferNode;
327 * 2. whether it is the current blocking BufferNode;
328 * 3. the name of the parent element;
329 * 4. the name of this element;
330 * 5. all ElementCollectors working on this BufferNode;
331 * 6. the Blocker working on this BufferNode;
332 * 7. all child BufferNodes' information.
334 * INPUTS
335 * pBufferNode - the BufferNode from where information will be retrieved.
336 * nIndent - how many space characters prefixed before the output
337 * message.
339 * RESULT
340 * info - the information string
342 * AUTHOR
343 * Michael Mi
344 * Email: michael.mi@sun.com
345 ******************************************************************************/
347 rtl::OUString rc;
349 for ( int i=0; i<nIndent; ++i )
351 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
354 if (pBufferNode == m_pCurrentBufferNode)
356 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
359 if (pBufferNode == m_pCurrentBlockingBufferNode)
361 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
364 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
365 rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
367 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
368 if (pParent != NULL)
370 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
371 rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
372 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
375 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
376 rc += pBufferNode->printChildren();
377 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));
379 ElementMark * pBlocker = pBufferNode->getBlocker();
380 if (pBlocker != NULL)
382 rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
383 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
384 rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
385 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
386 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
388 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
390 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
391 std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
392 for( ; jj != vChildren->end(); ++jj )
394 rc += printBufferNode((BufferNode *)*jj, nIndent+4);
397 delete vChildren;
399 return rc;
402 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
403 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
404 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
406 * NAME
407 * collectChildWorkingElement -- collects a BufferNode's all child
408 * Elements.
410 * SYNOPSIS
411 * list = collectChildWorkingElement( pBufferNode );
413 * FUNCTION
414 * see NAME.
416 * INPUTS
417 * pBufferNode - the BufferNode whose child Elements will be collected.
419 * RESULT
420 * list - the child Elements list.
422 * AUTHOR
423 * Michael Mi
424 * Email: michael.mi@sun.com
425 ******************************************************************************/
427 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
429 cssu::Sequence < cssu::Reference<
430 cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
432 std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
434 sal_Int32 nIndex = 0;
435 for( ; ii != vChildren->end(); ++ii )
437 aChildrenCollection[nIndex] = (*ii)->getXMLElement();
438 nIndex++;
441 delete vChildren;
443 return aChildrenCollection;
446 void SAXEventKeeperImpl::smashBufferNode(
447 BufferNode* pBufferNode, bool bClearRoot) const
448 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
450 * NAME
451 * smashBufferNode -- removes a BufferNode along with its working
452 * element.
454 * SYNOPSIS
455 * smashBufferNode( pBufferNode, bClearRoot );
457 * FUNCTION
458 * removes the BufferNode's working element from the DOM document, while
459 * reserves all ancestor paths for its child BufferNodes.
460 * when any of the BufferNode's ancestor element is useless, removes it
461 * too.
462 * removes the BufferNode from the BufferNode tree.
464 * INPUTS
465 * pBufferNode - the BufferNode to be removed
466 * bClearRoot - whether the root element also needs to be cleared up.
468 * RESULT
469 * empty
471 * NOTES
472 * when removeing a Blocker's BufferNode, the bClearRoot flag should be
473 * true. Because a Blocker can buffer many SAX events which are not used
474 * by any other ElementCollector or Blocker.
475 * When the bClearRoot is set to true, the root BufferNode will be first
476 * cleared, with a stop flag seting at the next Blocking BufferNode. This
477 * operation can delete all useless bufferred SAX events which are only
478 * needed by the Blocker to be deleted.
480 * AUTHOR
481 * Michael Mi
482 * Email: michael.mi@sun.com
483 ******************************************************************************/
485 if (!pBufferNode->hasAnything())
487 BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
490 * delete the XML data
492 if (pParent == m_pRootBufferNode)
494 bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
495 bool bIsBlockInside = false;
496 bool bIsBlockingAfterward = false;
499 * If this is a blocker, then remove any out-element data
500 * which caused by blocking. The removal process will stop
501 * at the next blokcer to avoid removing any useful data.
503 if (bClearRoot)
505 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
506 aChildElements = collectChildWorkingElement(m_pRootBufferNode);
509 * the clearUselessData only clearup the content in the
510 * node, not the node itself.
512 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
513 aChildElements,
514 bIsNotBlocking?(NULL):
515 (m_pCurrentBlockingBufferNode->getXMLElement()));
518 * remove the node if it is empty, then if its parent is also
519 * empty, remove it, then if the next parent is also empty,
520 * remove it,..., until parent become null.
522 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
526 * if blocking, check the relationship between this BufferNode and
527 * the current blocking BufferNode.
529 if ( !bIsNotBlocking )
532 * the current blocking BufferNode is a descendant of this BufferNode.
534 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
537 * the current blocking BufferNode locates behind this BufferNode in tree
538 * order.
540 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
544 * this BufferNode's working element needs to be deleted only when
545 * 1. there is no blocking, or
546 * 2. the current blocking BufferNode is a descendant of this BufferNode,
547 * (then in the BufferNode's working element, the useless data before the blocking
548 * element should be deleted.) or
549 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
550 * (then the useless data between the blocking element and the working element
551 * should be deleted.).
552 * Otherwise, this working element should not be deleted.
554 if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
556 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
557 aChildElements = collectChildWorkingElement(pBufferNode);
560 * the clearUselessData only clearup the content in the
561 * node, not the node itself.
563 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
564 aChildElements,
565 bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
566 (NULL));
569 * remove the node if it is empty, then if its parent is also
570 * empty, remove it, then if the next parent is also empty,
571 * remove it,..., until parent become null.
573 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
577 sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
579 std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
580 pParent->removeChild(pBufferNode);
581 pBufferNode->setParent(NULL);
583 std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
584 for( ; ii != vChildren->end(); ++ii )
586 ((BufferNode *)(*ii))->setParent(pParent);
587 pParent->addChild(*ii, nIndex);
588 nIndex++;
591 delete vChildren;
594 * delete the BufferNode
596 delete pBufferNode;
600 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
601 BufferNode* pStartBufferNode) const
602 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
604 * NAME
605 * findNextBlockingBufferNode -- finds the next blocking BufferNode
606 * behind the particular BufferNode.
608 * SYNOPSIS
609 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
611 * FUNCTION
612 * see NAME.
614 * INPUTS
615 * pStartBufferNode - the BufferNode from where to search the next
616 * blocking BufferNode.
618 * RESULT
619 * pBufferNode - the next blocking BufferNode, or NULL if no such
620 * BufferNode exists.
622 * AUTHOR
623 * Michael Mi
624 * Email: michael.mi@sun.com
625 ******************************************************************************/
627 BufferNode* pNext = NULL;
629 if (pStartBufferNode != NULL)
631 pNext = pStartBufferNode;
633 while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
635 if (pNext->getBlocker() != NULL)
637 break;
642 return pNext;
645 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
646 /****** SAXEventKeeperImpl/diffuse *******************************************
648 * NAME
649 * diffuse -- diffuse the notification.
651 * SYNOPSIS
652 * diffuse( pBufferNode );
654 * FUNCTION
655 * diffuse the collecting completion notification from the specific
656 * BufferNode along its parent link, until an ancestor which is not
657 * completely received is met.
659 * INPUTS
660 * pBufferNode - the BufferNode from which the notification will be
661 * diffused.
663 * RESULT
664 * empty
666 * AUTHOR
667 * Michael Mi
668 * Email: michael.mi@sun.com
669 ******************************************************************************/
671 BufferNode* pParent = pBufferNode;
673 while(pParent->isAllReceived())
675 pParent->elementCollectorNotify();
676 pParent = (BufferNode*)pParent->getParent();
680 void SAXEventKeeperImpl::releaseElementMarkBuffer()
681 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
683 * NAME
684 * releaseElementMarkBuffer -- releases useless ElementMarks
686 * SYNOPSIS
687 * releaseElementMarkBuffer( );
689 * FUNCTION
690 * releases each ElementMark in the releasing list
691 * m_vReleasedElementMarkBuffers.
692 * The operation differs between an ElementCollector and a Blocker.
694 * INPUTS
695 * empty
697 * RESULT
698 * empty
700 * AUTHOR
701 * Michael Mi
702 * Email: michael.mi@sun.com
703 ******************************************************************************/
705 m_bIsReleasing = true;
706 while (!m_vReleasedElementMarkBuffers.empty())
708 std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
709 sal_Int32 nId = *pId;
710 m_vReleasedElementMarkBuffers.erase( pId );
712 ElementMark* pElementMark = findElementMarkBuffer(nId);
714 if (pElementMark != NULL)
716 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
717 == pElementMark->getType())
719 * it is a EC
722 ElementCollector* pElementCollector = (ElementCollector*)pElementMark;
724 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
725 bool bToModify = pElementCollector->getModify();
728 * Delete the EC from the buffer node.
730 BufferNode* pBufferNode = pElementCollector->getBufferNode();
731 pBufferNode->removeElementCollector(pElementCollector);
733 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
735 pBufferNode->notifyBranch();
738 if (bToModify)
740 pBufferNode->notifyAncestor();
744 * delete the ElementMark
746 pElementCollector = NULL;
747 pElementMark = NULL;
748 removeElementMarkBuffer(nId);
751 * delete the BufferNode
753 diffuse(pBufferNode);
754 smashBufferNode(pBufferNode, false);
756 else
758 * it is a Blocker
762 * Delete the TH from the buffer node.
764 BufferNode *pBufferNode = pElementMark->getBufferNode();
765 pBufferNode->setBlocker(NULL);
768 * If there is a following handler and no blocking now, then
769 * forward this event
771 if (m_pCurrentBlockingBufferNode == pBufferNode)
774 * Before forwarding, the next blocking point needs to be
775 * found.
777 m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
780 * Forward the blocked events between these two STHs.
782 if (m_xNextHandler.is())
784 BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
785 BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
787 m_pCurrentBufferNode = pBufferNode;
788 m_pCurrentBlockingBufferNode = NULL;
790 m_bIsForwarding = true;
792 m_xXMLDocument->generateSAXEvents(
793 m_xNextHandler,
794 this,
795 pBufferNode->getXMLElement(),
796 (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
798 m_bIsForwarding = false;
800 m_pCurrentBufferNode = pTempCurrentBufferNode;
801 if (m_pCurrentBlockingBufferNode == NULL)
803 m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
807 if (m_pCurrentBlockingBufferNode == NULL &&
808 m_xSAXEventKeeperStatusChangeListener.is())
810 m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
815 * delete the ElementMark
817 pElementMark = NULL;
818 removeElementMarkBuffer(nId);
821 * delete the BufferNode
823 diffuse(pBufferNode);
824 smashBufferNode(pBufferNode, true);
829 m_bIsReleasing = false;
831 if (!m_pRootBufferNode->hasAnything() &&
832 !m_pRootBufferNode->hasChildren() &&
833 m_xSAXEventKeeperStatusChangeListener.is())
835 m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
839 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
840 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
842 * NAME
843 * markElementMarkBuffer -- marks an ElementMark to be released
845 * SYNOPSIS
846 * markElementMarkBuffer( nId );
848 * FUNCTION
849 * puts the ElementMark with the particular Id into the releasing list,
850 * checks whether the releasing process is runing, if not then launch
851 * this process.
853 * INPUTS
854 * nId - the Id of the ElementMark which will be released
856 * RESULT
857 * empty
859 * AUTHOR
860 * Michael Mi
861 * Email: michael.mi@sun.com
862 ******************************************************************************/
864 m_vReleasedElementMarkBuffers.push_back( nId );
865 if ( !m_bIsReleasing )
867 releaseElementMarkBuffer();
871 sal_Int32 SAXEventKeeperImpl::createElementCollector(
872 sal_Int32 nSecurityId,
873 cssxc::sax::ElementMarkPriority nPriority,
874 bool bModifyElement,
875 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
876 /****** SAXEventKeeperImpl/createElementCollector ****************************
878 * NAME
879 * createElementCollector -- creates a new ElementCollector on the
880 * incoming element.
882 * SYNOPSIS
883 * nId = createElementCollector( nSecurityId, nPriority,
884 * bModifyElement,
885 * xReferenceResolvedListener );
887 * FUNCTION
888 * allocs a new Id, then create an ElementCollector with this Id value.
889 * Add the new created ElementCollector to the new ElementCollecotor list.
891 * INPUTS
892 * nSecurityId - the security Id of the new ElementCollector
893 * nPriority - the prirority of the new ElementCollector
894 * bModifyElement -whether this BufferNode will modify the content of
895 * the corresponding element it works on
896 * xReferenceResolvedListener - the listener for the new ElementCollector.
898 * RESULT
899 * nId - the Id of the new ElementCollector
901 * AUTHOR
902 * Michael Mi
903 * Email: michael.mi@sun.com
904 ******************************************************************************/
906 sal_Int32 nId = m_nNextElementMarkId;
907 m_nNextElementMarkId ++;
909 ElementCollector* pElementCollector
910 = new ElementCollector(
911 nSecurityId,
912 nId,
913 nPriority,
914 bModifyElement,
915 xReferenceResolvedListener);
917 m_vElementMarkBuffers.push_back( pElementCollector );
920 * All the new EC to initial EC array.
922 m_vNewElementCollectors.push_back( pElementCollector );
924 return nId;
928 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
929 /****** SAXEventKeeperImpl/createBlocker *************************************
931 * NAME
932 * createBlocker -- creates a new Blocker on the incoming element.
934 * SYNOPSIS
935 * nId = createBlocker( nSecurityId );
937 * FUNCTION
938 * see NAME.
940 * INPUTS
941 * nSecurityId - the security Id of the new Blocker
943 * RESULT
944 * nId - the Id of the new Blocker
946 * AUTHOR
947 * Michael Mi
948 * Email: michael.mi@sun.com
949 ******************************************************************************/
951 sal_Int32 nId = m_nNextElementMarkId;
952 m_nNextElementMarkId ++;
954 OSL_ASSERT(m_pNewBlocker == NULL);
956 m_pNewBlocker = new ElementMark(nSecurityId, nId);
957 m_vElementMarkBuffers.push_back( m_pNewBlocker );
959 return nId;
962 /* XSAXEventKeeper */
963 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
964 throw (cssu::RuntimeException)
966 return createElementCollector(
967 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
968 cssxc::sax::ElementMarkPriority_AFTERMODIFY,
969 false,
970 NULL);
973 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
974 throw (cssu::RuntimeException)
976 markElementMarkBuffer(id);
979 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
980 throw (cssu::RuntimeException)
982 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
985 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
986 throw (cssu::RuntimeException)
988 markElementMarkBuffer(id);
991 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
992 throw (cssu::RuntimeException)
994 return (m_pCurrentBlockingBufferNode != NULL);
997 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
998 SAXEventKeeperImpl::getElement( sal_Int32 id )
999 throw (cssu::RuntimeException)
1001 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1003 ElementMark* pElementMark = findElementMarkBuffer(id);
1004 if (pElementMark != NULL)
1006 rc = pElementMark->getBufferNode()->getXMLElement();
1009 return rc;
1012 void SAL_CALL SAXEventKeeperImpl::setElement(
1013 sal_Int32 id,
1014 const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1015 throw (cssu::RuntimeException)
1017 if (aElement.is())
1019 m_xXMLDocument->rebuildIDLink(aElement);
1021 ElementMark* pElementMark = findElementMarkBuffer(id);
1023 if (pElementMark != NULL)
1025 BufferNode* pBufferNode = pElementMark->getBufferNode();
1026 if (pBufferNode != NULL)
1028 bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1029 pBufferNode->setXMLElement(aElement);
1031 if (bIsCurrent)
1033 m_xXMLDocument->setCurrentElement(aElement);
1038 else
1040 removeElementCollector( id );
1044 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1045 const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1046 throw (cssu::RuntimeException)
1048 cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1050 m_xNextHandler = xNewHandler;
1051 return xOldHandler;
1054 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1055 throw (cssu::RuntimeException)
1057 rtl::OUString rc;
1059 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
1060 rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
1061 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
1062 rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1063 rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
1064 rc += printBufferNode(m_pRootBufferNode, 0);
1066 return rc;
1069 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1070 throw (cssu::RuntimeException)
1072 cssu::Reference< cssxw::XXMLElementWrapper > rc;
1074 if (m_pCurrentBlockingBufferNode != NULL)
1076 rc = m_pCurrentBlockingBufferNode->getXMLElement();
1079 return rc;
1082 /* XSecuritySAXEventKeeper */
1083 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1084 cssxc::sax::ElementMarkPriority priority,
1085 sal_Bool modifyElement )
1086 throw (cssu::RuntimeException)
1088 return createElementCollector(
1089 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1090 priority,
1091 modifyElement,
1092 NULL);
1095 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1096 sal_Int32 referenceId,
1097 cssxc::sax::ElementMarkPriority priority )
1098 throw (cssu::RuntimeException)
1100 sal_Int32 nId = -1;
1102 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1103 if (pElementCollector != NULL)
1105 nId = m_nNextElementMarkId;
1106 m_nNextElementMarkId ++;
1108 ElementCollector* pClonedOne
1109 = pElementCollector->clone(nId, priority);
1112 * add this EC into the security data buffer array.
1114 m_vElementMarkBuffers.push_back(pClonedOne);
1117 * If the reference EC is still in initial EC array, add
1118 * this cloned one into the initial EC array too.
1120 if (pElementCollector->getBufferNode() == NULL)
1122 m_vNewElementCollectors.push_back(pClonedOne);
1126 return nId;
1129 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1130 throw (cssu::RuntimeException)
1132 ElementMark* pElementMark = findElementMarkBuffer(id);
1133 if (pElementMark != NULL)
1135 pElementMark->setSecurityId(securityId);
1140 /* XReferenceResolvedBroadcaster */
1141 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1142 sal_Int32 referenceId,
1143 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1144 throw (cssu::RuntimeException)
1146 ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1147 if (pElementCollector != NULL)
1149 pElementCollector->setReferenceResolvedListener(listener);
1153 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1154 sal_Int32 /*referenceId*/,
1155 const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1156 throw (cssu::RuntimeException)
1160 /* XSAXEventKeeperStatusChangeBroadcaster */
1161 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1162 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1163 throw (cssu::RuntimeException)
1165 m_xSAXEventKeeperStatusChangeListener = listener;
1168 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1169 const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1170 throw (cssu::RuntimeException)
1174 /* XDocumentHandler */
1175 void SAL_CALL SAXEventKeeperImpl::startDocument( )
1176 throw (cssxs::SAXException, cssu::RuntimeException)
1178 if ( m_xNextHandler.is())
1180 m_xNextHandler->startDocument();
1184 void SAL_CALL SAXEventKeeperImpl::endDocument( )
1185 throw (cssxs::SAXException, cssu::RuntimeException)
1187 if ( m_xNextHandler.is())
1189 m_xNextHandler->endDocument();
1193 void SAL_CALL SAXEventKeeperImpl::startElement(
1194 const rtl::OUString& aName,
1195 const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1196 throw (cssxs::SAXException, cssu::RuntimeException)
1199 * If there is a following handler and no blocking now, then
1200 * forward this event
1202 if ((m_pCurrentBlockingBufferNode == NULL) &&
1203 (m_xNextHandler.is()) &&
1204 (!m_bIsForwarding) &&
1205 (m_pNewBlocker == NULL))
1207 m_xNextHandler->startElement(aName, xAttribs);
1211 * If not forwarding, buffer this startElement.
1213 if (!m_bIsForwarding)
1215 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1216 m_xDocumentHandler->startElement(aName, xAttribs);
1217 #else
1218 sal_Int32 nLength = xAttribs->getLength();
1219 cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1221 for ( int i = 0; i<nLength; ++i )
1223 aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1224 aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1227 m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
1228 #endif
1232 BufferNode* pBufferNode = addNewElementMarkBuffers();
1233 if (pBufferNode != NULL)
1235 setCurrentBufferNode(pBufferNode);
1239 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
1240 throw (cssxs::SAXException, cssu::RuntimeException)
1242 sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1245 * If there is a following handler and no blocking now, then
1246 * forward this event
1248 if ((m_pCurrentBlockingBufferNode == NULL) &&
1249 (m_xNextHandler.is()) &&
1250 (!m_bIsForwarding))
1252 m_xNextHandler->endElement(aName);
1255 if ((m_pCurrentBlockingBufferNode != NULL) ||
1256 (m_pCurrentBufferNode != m_pRootBufferNode) ||
1257 (!m_xXMLDocument->isCurrentElementEmpty()))
1259 if (!m_bIsForwarding)
1261 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1262 m_xDocumentHandler->endElement(aName);
1263 #else
1264 m_xCompressedDocumentHandler->_endElement(aName);
1265 #endif
1269 * If the current buffer node has not notified yet, and
1270 * the current buffer node is waiting for the current element,
1271 * then let it notify.
1273 if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1275 BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1276 m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
1278 pOldCurrentBufferNode->setReceivedAll();
1280 if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1281 m_xSAXEventKeeperStatusChangeListener.is())
1283 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1287 else
1289 if (!m_bIsForwarding)
1291 m_xXMLDocument->removeCurrentElement();
1296 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
1297 throw (cssxs::SAXException, cssu::RuntimeException)
1299 if (!m_bIsForwarding)
1301 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1303 m_xNextHandler->characters(aChars);
1306 if ((m_pCurrentBlockingBufferNode != NULL) ||
1307 (m_pCurrentBufferNode != m_pRootBufferNode))
1309 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1310 m_xDocumentHandler->characters(aChars);
1311 #else
1312 m_xCompressedDocumentHandler->_characters(aChars);
1313 #endif
1318 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1319 throw (cssxs::SAXException, cssu::RuntimeException)
1321 characters( aWhitespaces );
1324 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1325 const rtl::OUString& aTarget, const rtl::OUString& aData )
1326 throw (cssxs::SAXException, cssu::RuntimeException)
1328 if (!m_bIsForwarding)
1330 if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1332 m_xNextHandler->processingInstruction(aTarget, aData);
1335 if ((m_pCurrentBlockingBufferNode != NULL) ||
1336 (m_pCurrentBufferNode != m_pRootBufferNode))
1338 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1339 m_xDocumentHandler->processingInstruction(aTarget, aData);
1340 #else
1341 m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
1342 #endif
1347 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1348 throw (cssxs::SAXException, cssu::RuntimeException)
1352 /* XInitialization */
1353 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1354 throw (cssu::Exception, cssu::RuntimeException)
1356 OSL_ASSERT(aArguments.getLength() == 1);
1358 aArguments[0] >>= m_xXMLDocument;
1359 m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1360 m_xXMLDocument, cssu::UNO_QUERY );
1361 m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1362 m_xXMLDocument, cssu::UNO_QUERY );
1364 m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1365 m_pCurrentBufferNode = m_pRootBufferNode;
1368 rtl::OUString SAXEventKeeperImpl_getImplementationName ()
1369 throw (cssu::RuntimeException)
1371 return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1374 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
1375 throw (cssu::RuntimeException)
1377 return ServiceName == SERVICE_NAME;
1380 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( )
1381 throw (cssu::RuntimeException)
1383 cssu::Sequence < rtl::OUString > aRet(1);
1384 rtl::OUString* pArray = aRet.getArray();
1385 pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1386 return aRet;
1388 #undef SERVICE_NAME
1390 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1391 const cssu::Reference< cssl::XMultiServiceFactory > &)
1392 throw( cssu::Exception )
1394 return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1397 /* XServiceInfo */
1398 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
1399 throw (cssu::RuntimeException)
1401 return SAXEventKeeperImpl_getImplementationName();
1403 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
1404 throw (cssu::RuntimeException)
1406 return SAXEventKeeperImpl_supportsService( rServiceName );
1408 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
1409 throw (cssu::RuntimeException)
1411 return SAXEventKeeperImpl_getSupportedServiceNames();
1414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */