1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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),
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();
71 std::vector
< const ElementMark
* >::const_iterator ii
= m_vElementMarkBuffers
.begin();
72 for( ; ii
!= m_vElementMarkBuffers
.end(); ++ii
)
76 m_vElementMarkBuffers
.clear();
79 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode
* pBufferNode
)
80 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
83 * setCurrentBufferNode -- set a new active BufferNode.
86 * setCurrentBufferNode( pBufferNode );
89 * connects this BufferNode into the BufferNode tree as a child of the
90 * current active BufferNode. Then makes this BufferNode as the current
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
98 * pBufferNode - a BufferNode which will be the new active BufferNode
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 **************************
130 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
133 * pBufferNode = addNewElementMarkBuffers( );
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.
145 * pBufferNode - the BufferNode that has been connected with both new
146 * ElementCollectors and new Blocker.
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
;
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();
211 ElementMark
* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId
) const
212 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
215 * findElementMarkBuffer -- finds an ElementMark.
218 * pElementMark = findElementMarkBuffer( nId );
221 * searches an ElementMark with the particular Id in the ElementMark
225 * nId - the Id of the ElementMark to be searched.
228 * pElementMark - the ElementMark with the particular Id, or NULL when
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
;
252 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId
)
253 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
256 * removeElementMarkBuffer -- removes an ElementMark
259 * removeElementMarkBuffer( nId );
262 * removes an ElementMark with the particular Id in the ElementMark list.
265 * nId - the Id of the ElementMark to be removed.
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
)
289 m_vNewElementCollectors
.erase(jj
);
295 * checks whether this ElementMark is the new Blocker
297 if ((*ii
) == m_pNewBlocker
)
299 m_pNewBlocker
= NULL
;
303 * destory the ElementMark
307 m_vElementMarkBuffers
.erase( ii
);
313 rtl::OUString
SAXEventKeeperImpl::printBufferNode(
314 BufferNode
* pBufferNode
, sal_Int32 nIndent
) const
315 /****** SAXEventKeeperImpl/printBufferNode ***********************************
318 * printBufferNode -- retrieves the information of a BufferNode and its
322 * info = printBufferNode( pBufferNode, nIndent );
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.
335 * pBufferNode - the BufferNode from where information will be retrieved.
336 * nIndent - how many space characters prefixed before the output
340 * info - the information string
344 * Email: michael.mi@sun.com
345 ******************************************************************************/
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();
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);
402 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
403 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode
* pBufferNode
) const
404 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
407 * collectChildWorkingElement -- collects a BufferNode's all child
411 * list = collectChildWorkingElement( pBufferNode );
417 * pBufferNode - the BufferNode whose child Elements will be collected.
420 * list - the child Elements list.
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();
443 return aChildrenCollection
;
446 void SAXEventKeeperImpl::smashBufferNode(
447 BufferNode
* pBufferNode
, bool bClearRoot
) const
448 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
451 * smashBufferNode -- removes a BufferNode along with its working
455 * smashBufferNode( pBufferNode, bClearRoot );
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
462 * removes the BufferNode from the BufferNode tree.
465 * pBufferNode - the BufferNode to be removed
466 * bClearRoot - whether the root element also needs to be cleared up.
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.
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.
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(),
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
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(),
565 bIsBlockInside
?(m_pCurrentBlockingBufferNode
->getXMLElement()):
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
);
594 * delete the BufferNode
600 BufferNode
* SAXEventKeeperImpl::findNextBlockingBufferNode(
601 BufferNode
* pStartBufferNode
) const
602 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
605 * findNextBlockingBufferNode -- finds the next blocking BufferNode
606 * behind the particular BufferNode.
609 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
615 * pStartBufferNode - the BufferNode from where to search the next
616 * blocking BufferNode.
619 * pBufferNode - the next blocking BufferNode, or NULL if no such
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
)
645 void SAXEventKeeperImpl::diffuse(BufferNode
* pBufferNode
) const
646 /****** SAXEventKeeperImpl/diffuse *******************************************
649 * diffuse -- diffuse the notification.
652 * diffuse( pBufferNode );
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.
660 * pBufferNode - the BufferNode from which the notification will be
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 **************************
684 * releaseElementMarkBuffer -- releases useless ElementMarks
687 * releaseElementMarkBuffer( );
690 * releases each ElementMark in the releasing list
691 * m_vReleasedElementMarkBuffers.
692 * The operation differs between an ElementCollector and a Blocker.
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())
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();
740 pBufferNode
->notifyAncestor();
744 * delete the ElementMark
746 pElementCollector
= NULL
;
748 removeElementMarkBuffer(nId
);
751 * delete the BufferNode
753 diffuse(pBufferNode
);
754 smashBufferNode(pBufferNode
, false);
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
771 if (m_pCurrentBlockingBufferNode
== pBufferNode
)
774 * Before forwarding, the next blocking point needs to be
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(
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
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 *****************************
843 * markElementMarkBuffer -- marks an ElementMark to be released
846 * markElementMarkBuffer( nId );
849 * puts the ElementMark with the particular Id into the releasing list,
850 * checks whether the releasing process is runing, if not then launch
854 * nId - the Id of the ElementMark which will be released
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
,
875 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& xReferenceResolvedListener
)
876 /****** SAXEventKeeperImpl/createElementCollector ****************************
879 * createElementCollector -- creates a new ElementCollector on the
883 * nId = createElementCollector( nSecurityId, nPriority,
885 * xReferenceResolvedListener );
888 * allocs a new Id, then create an ElementCollector with this Id value.
889 * Add the new created ElementCollector to the new ElementCollecotor list.
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.
899 * nId - the Id of the new ElementCollector
903 * Email: michael.mi@sun.com
904 ******************************************************************************/
906 sal_Int32 nId
= m_nNextElementMarkId
;
907 m_nNextElementMarkId
++;
909 ElementCollector
* pElementCollector
910 = new ElementCollector(
915 xReferenceResolvedListener
);
917 m_vElementMarkBuffers
.push_back( pElementCollector
);
920 * All the new EC to initial EC array.
922 m_vNewElementCollectors
.push_back( pElementCollector
);
928 sal_Int32
SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId
)
929 /****** SAXEventKeeperImpl/createBlocker *************************************
932 * createBlocker -- creates a new Blocker on the incoming element.
935 * nId = createBlocker( nSecurityId );
941 * nSecurityId - the security Id of the new Blocker
944 * nId - the Id of the new Blocker
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
);
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
,
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();
1012 void SAL_CALL
SAXEventKeeperImpl::setElement(
1014 const cssu::Reference
< cssxw::XXMLElementWrapper
>& aElement
)
1015 throw (cssu::RuntimeException
)
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
);
1033 m_xXMLDocument
->setCurrentElement(aElement
);
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
;
1054 rtl::OUString SAL_CALL
SAXEventKeeperImpl::printBufferNodeTree()
1055 throw (cssu::RuntimeException
)
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);
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();
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
,
1095 sal_Int32 SAL_CALL
SAXEventKeeperImpl::cloneElementCollector(
1096 sal_Int32 referenceId
,
1097 cssxc::sax::ElementMarkPriority priority
)
1098 throw (cssu::RuntimeException
)
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
);
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
);
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
);
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()) &&
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
);
1264 m_xCompressedDocumentHandler
->_endElement(aName
);
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
);
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
);
1312 m_xCompressedDocumentHandler
->_characters(aChars
);
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
);
1341 m_xCompressedDocumentHandler
->_processingInstruction(aTarget
, aData
);
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
) );
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();
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: */