1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: saxeventkeeperimpl.cxx,v $
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),
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();
84 std::vector
< const ElementMark
* >::const_iterator ii
= m_vElementMarkBuffers
.begin();
85 for( ; ii
!= m_vElementMarkBuffers
.end(); ++ii
)
89 m_vElementMarkBuffers
.clear();
92 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode
* pBufferNode
)
93 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
96 * setCurrentBufferNode -- set a new active BufferNode.
99 * setCurrentBufferNode( pBufferNode );
102 * connects this BufferNode into the BufferNode tree as a child of the
103 * current active BufferNode. Then makes this BufferNode as the current
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.
111 * pBufferNode - a BufferNode which will be the new active BufferNode
117 * 05.01.2004 - implemented
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 **************************
146 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
149 * pBufferNode = addNewElementMarkBuffers( );
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.
161 * pBufferNode - the BufferNode that has been connected with both new
162 * ElementCollectors and new Blocker.
165 * 05.01.2004 - implemented
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
;
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();
231 ElementMark
* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId
) const
232 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
235 * findElementMarkBuffer -- finds an ElementMark.
238 * pElementMark = findElementMarkBuffer( nId );
241 * searches an ElementMark with the particular Id in the ElementMark
245 * nId - the Id of the ElementMark to be searched.
248 * pElementMark - the ElementMark with the particular Id, or NULL when
252 * 05.01.2004 - implemented
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
;
275 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId
)
276 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
279 * removeElementMarkBuffer -- removes an ElementMark
282 * removeElementMarkBuffer( nId );
285 * removes an ElementMark with the particular Id in the ElementMark list.
288 * nId - the Id of the ElementMark to be removed.
294 * 05.01.2004 - implemented
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
)
315 m_vNewElementCollectors
.erase(jj
);
321 * checks whether this ElementMark is the new Blocker
323 if ((*ii
) == m_pNewBlocker
)
325 m_pNewBlocker
= NULL
;
329 * destory the ElementMark
333 m_vElementMarkBuffers
.erase( ii
);
339 rtl::OUString
SAXEventKeeperImpl::printBufferNode(
340 BufferNode
* pBufferNode
, sal_Int32 nIndent
) const
341 /****** SAXEventKeeperImpl/printBufferNode ***********************************
344 * printBufferNode -- retrieves the information of a BufferNode and its
348 * info = printBufferNode( pBufferNode, nIndent );
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.
361 * pBufferNode - the BufferNode from where information will be retrieved.
362 * nIndent - how many space characters prefixed before the output
366 * info - the information string
369 * 05.01.2004 - implemented
373 * Email: michael.mi@sun.com
374 ******************************************************************************/
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();
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);
431 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
432 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode
* pBufferNode
) const
433 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
436 * collectChildWorkingElement -- collects a BufferNode's all child
440 * list = collectChildWorkingElement( pBufferNode );
446 * pBufferNode - the BufferNode whose child Elements will be collected.
449 * list - the child Elements list.
452 * 05.01.2004 - implemented
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();
475 return aChildrenCollection
;
478 void SAXEventKeeperImpl::smashBufferNode(
479 BufferNode
* pBufferNode
, bool bClearRoot
) const
480 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
483 * smashBufferNode -- removes a BufferNode along with its working
487 * smashBufferNode( pBufferNode, bClearRoot );
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
494 * removes the BufferNode from the BufferNode tree.
497 * pBufferNode - the BufferNode to be removed
498 * bClearRoot - whether the root element also needs to be cleared up.
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.
513 * 05.01.2004 - implemented
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.
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(),
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
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(),
600 bIsBlockInside
?(m_pCurrentBlockingBufferNode
->getXMLElement()):
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
);
629 * delete the BufferNode
635 BufferNode
* SAXEventKeeperImpl::findNextBlockingBufferNode(
636 BufferNode
* pStartBufferNode
) const
637 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
640 * findNextBlockingBufferNode -- finds the next blocking BufferNode
641 * behind the particular BufferNode.
644 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
650 * pStartBufferNode - the BufferNode from where to search the next
651 * blocking BufferNode.
654 * pBufferNode - the next blocking BufferNode, or NULL if no such
658 * 05.01.2004 - implemented
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
)
683 void SAXEventKeeperImpl::diffuse(BufferNode
* pBufferNode
) const
684 /****** SAXEventKeeperImpl/diffuse *******************************************
687 * diffuse -- diffuse the notification.
690 * diffuse( pBufferNode );
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.
698 * pBufferNode - the BufferNode from which the notification will be
705 * 05.01.2004 - implemented
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 **************************
725 * releaseElementMarkBuffer -- releases useless ElementMarks
728 * releaseElementMarkBuffer( );
731 * releases each ElementMark in the releasing list
732 * m_vReleasedElementMarkBuffers.
733 * The operation differs between an ElementCollector and a Blocker.
742 * 05.01.2004 - implemented
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())
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();
784 pBufferNode
->notifyAncestor();
788 * delete the ElementMark
790 pElementCollector
= NULL
;
792 removeElementMarkBuffer(nId
);
795 * delete the BufferNode
797 diffuse(pBufferNode
);
798 smashBufferNode(pBufferNode
, false);
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
815 if (m_pCurrentBlockingBufferNode
== pBufferNode
)
818 * Before forwarding, the next blocking point needs to be
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(
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
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 *****************************
887 * markElementMarkBuffer -- marks an ElementMark to be released
890 * markElementMarkBuffer( nId );
893 * puts the ElementMark with the particular Id into the releasing list,
894 * checks whether the releasing process is runing, if not then launch
898 * nId - the Id of the ElementMark which will be released
904 * 05.01.2004 - implemented
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
,
922 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& xReferenceResolvedListener
)
923 /****** SAXEventKeeperImpl/createElementCollector ****************************
926 * createElementCollector -- creates a new ElementCollector on the
930 * nId = createElementCollector( nSecurityId, nPriority,
932 * xReferenceResolvedListener );
935 * allocs a new Id, then create an ElementCollector with this Id value.
936 * Add the new created ElementCollector to the new ElementCollecotor list.
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.
946 * nId - the Id of the new ElementCollector
949 * 05.01.2004 - implemented
953 * Email: michael.mi@sun.com
954 ******************************************************************************/
956 sal_Int32 nId
= m_nNextElementMarkId
;
957 m_nNextElementMarkId
++;
959 ElementCollector
* pElementCollector
960 = new ElementCollector(
965 xReferenceResolvedListener
);
967 m_vElementMarkBuffers
.push_back( pElementCollector
);
970 * All the new EC to initial EC array.
972 m_vNewElementCollectors
.push_back( pElementCollector
);
978 sal_Int32
SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId
)
979 /****** SAXEventKeeperImpl/createBlocker *************************************
982 * createBlocker -- creates a new Blocker on the incoming element.
985 * nId = createBlocker( nSecurityId );
991 * nSecurityId - the security Id of the new Blocker
994 * nId - the Id of the new Blocker
997 * 05.01.2004 - implemented
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
);
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
,
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();
1065 void SAL_CALL
SAXEventKeeperImpl::setElement(
1067 const cssu::Reference
< cssxw::XXMLElementWrapper
>& aElement
)
1068 throw (cssu::RuntimeException
)
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
);
1086 m_xXMLDocument
->setCurrentElement(aElement
);
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
;
1107 rtl::OUString SAL_CALL
SAXEventKeeperImpl::printBufferNodeTree()
1108 throw (cssu::RuntimeException
)
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);
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();
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
,
1148 sal_Int32 SAL_CALL
SAXEventKeeperImpl::cloneElementCollector(
1149 sal_Int32 referenceId
,
1150 cssxc::sax::ElementMarkPriority priority
)
1151 throw (cssu::RuntimeException
)
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
);
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
);
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
);
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()) &&
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
);
1317 m_xCompressedDocumentHandler
->_endElement(aName
);
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
);
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
);
1365 m_xCompressedDocumentHandler
->_characters(aChars
);
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
);
1394 m_xCompressedDocumentHandler
->_processingInstruction(aTarget
, aData
);
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
) );
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();
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();