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