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>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <osl/diagnose.h>
28 namespace cssu
= com::sun::star::uno
;
29 namespace cssl
= com::sun::star::lang
;
30 namespace cssxc
= com::sun::star::xml::crypto
;
31 namespace cssxcsax
= com::sun::star::xml::csax
;
32 namespace cssxw
= com::sun::star::xml::wrapper
;
33 namespace cssxs
= com::sun::star::xml::sax
;
35 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
37 #define _USECOMPRESSEDDOCUMENTHANDLER
39 SAXEventKeeperImpl::SAXEventKeeperImpl( )
40 :m_pRootBufferNode(NULL
),
41 m_pCurrentBufferNode(NULL
),
42 m_nNextElementMarkId(1),
44 m_pCurrentBlockingBufferNode(NULL
),
45 m_bIsReleasing(false),
46 m_bIsForwarding(false)
48 m_vElementMarkBuffers
.reserve(2);
49 m_vNewElementCollectors
.reserve(2);
50 m_vReleasedElementMarkBuffers
.reserve(2);
53 SAXEventKeeperImpl::~SAXEventKeeperImpl()
56 * delete the BufferNode tree
58 if (m_pRootBufferNode
!= NULL
)
60 m_pRootBufferNode
->freeAllChildren();
61 delete m_pRootBufferNode
;
64 m_pRootBufferNode
= m_pCurrentBufferNode
= m_pCurrentBlockingBufferNode
= NULL
;
67 * delete all unfreed ElementMarks
69 m_vNewElementCollectors
.clear();
72 std::vector
< const ElementMark
* >::const_iterator ii
= m_vElementMarkBuffers
.begin();
73 for( ; ii
!= m_vElementMarkBuffers
.end(); ++ii
)
77 m_vElementMarkBuffers
.clear();
80 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode
* pBufferNode
)
81 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
84 * setCurrentBufferNode -- set a new active BufferNode.
87 * setCurrentBufferNode( pBufferNode );
90 * connects this BufferNode into the BufferNode tree as a child of the
91 * current active BufferNode. Then makes this BufferNode as the current
93 * If the previous active BufferNode points to the root
94 * BufferNode, which means that no buffering operation was proceeding,
95 * then notifies the status change listener that buffering operation
99 * pBufferNode - a BufferNode which will be the new active BufferNode
106 * Email: michael.mi@sun.com
107 ******************************************************************************/
109 if (pBufferNode
!= m_pCurrentBufferNode
)
111 if ( m_pCurrentBufferNode
== m_pRootBufferNode
&&
112 m_xSAXEventKeeperStatusChangeListener
.is())
114 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(sal_True
);
117 if (pBufferNode
->getParent() == NULL
)
119 m_pCurrentBufferNode
->addChild(pBufferNode
);
120 pBufferNode
->setParent(m_pCurrentBufferNode
);
123 m_pCurrentBufferNode
= pBufferNode
;
127 BufferNode
* SAXEventKeeperImpl::addNewElementMarkBuffers()
128 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
131 * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
134 * pBufferNode = addNewElementMarkBuffers( );
137 * if there are new ElementCollector or new Blocker to be added, then
138 * connect all of them with the current BufferNode. In case of the
139 * current BufferNode doesn't exist, creates one.
140 * Clears up the new ElementCollector list and the new Blocker pointer.
146 * pBufferNode - the BufferNode that has been connected with both new
147 * ElementCollectors and new Blocker.
151 * Email: michael.mi@sun.com
152 ******************************************************************************/
154 BufferNode
* pBufferNode
= NULL
;
156 if (m_pNewBlocker
|| !m_vNewElementCollectors
.empty() )
159 * When the current BufferNode is right pointing to the current
160 * working element in the XMLDocumentWrapper component, then
161 * no new BufferNode is needed to create.
162 * This situation can only happen in the "Forwarding" mode.
164 if ( (m_pCurrentBufferNode
!= NULL
) &&
165 (m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement())))
167 pBufferNode
= m_pCurrentBufferNode
;
171 pBufferNode
= new BufferNode(m_xXMLDocument
->getCurrentElement());
174 if (m_pNewBlocker
!= NULL
)
176 pBufferNode
->setBlocker(m_pNewBlocker
);
179 * If no blocking before, then notify the status change listener that
180 * the SAXEventKeeper has entered "blocking" status, during which, no
181 * SAX events will be forwarded to the next document handler.
183 if (m_pCurrentBlockingBufferNode
== NULL
)
185 m_pCurrentBlockingBufferNode
= pBufferNode
;
187 if (m_xSAXEventKeeperStatusChangeListener
.is())
189 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(sal_True
);
193 m_pNewBlocker
= NULL
;
196 if (!m_vNewElementCollectors
.empty())
198 std::vector
< const ElementCollector
* >::const_iterator ii
= m_vNewElementCollectors
.begin();
200 for( ; ii
!= m_vNewElementCollectors
.end(); ++ii
)
202 pBufferNode
->addElementCollector(*ii
);
205 m_vNewElementCollectors
.clear();
212 ElementMark
* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId
) const
213 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
216 * findElementMarkBuffer -- finds an ElementMark.
219 * pElementMark = findElementMarkBuffer( nId );
222 * searches an ElementMark with the particular Id in the ElementMark
226 * nId - the Id of the ElementMark to be searched.
229 * pElementMark - the ElementMark with the particular Id, or NULL when
234 * Email: michael.mi@sun.com
235 ******************************************************************************/
237 ElementMark
* pElementMark
= NULL
;
239 std::vector
< const ElementMark
* >::const_iterator ii
= m_vElementMarkBuffers
.begin();
241 for( ; ii
!= m_vElementMarkBuffers
.end(); ++ii
)
243 if ( nId
== (*ii
)->getBufferId())
245 pElementMark
= const_cast<ElementMark
*>(*ii
);
253 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId
)
254 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
257 * removeElementMarkBuffer -- removes an ElementMark
260 * removeElementMarkBuffer( nId );
263 * removes an ElementMark with the particular Id in the ElementMark list.
266 * nId - the Id of the ElementMark to be removed.
273 * Email: michael.mi@sun.com
274 ******************************************************************************/
276 std::vector
< const ElementMark
* >::iterator ii
= m_vElementMarkBuffers
.begin();
278 for( ; ii
!= m_vElementMarkBuffers
.end(); ++ii
)
280 if ( nId
== (*ii
)->getBufferId())
283 * checks whether this ElementMark still in the new ElementCollect array
285 std::vector
< const ElementCollector
* >::iterator jj
= m_vNewElementCollectors
.begin();
286 for( ; jj
!= m_vNewElementCollectors
.end(); ++jj
)
290 m_vNewElementCollectors
.erase(jj
);
296 * checks whether this ElementMark is the new Blocker
298 if ((*ii
) == m_pNewBlocker
)
300 m_pNewBlocker
= NULL
;
304 * destroy the ElementMark
308 m_vElementMarkBuffers
.erase( ii
);
314 OUString
SAXEventKeeperImpl::printBufferNode(
315 BufferNode
* pBufferNode
, sal_Int32 nIndent
) const
316 /****** SAXEventKeeperImpl/printBufferNode ***********************************
319 * printBufferNode -- retrieves the information of a BufferNode and its
323 * info = printBufferNode( pBufferNode, nIndent );
326 * all retrieved information includes:
327 * 1. whether it is the current BufferNode;
328 * 2. whether it is the current blocking BufferNode;
329 * 3. the name of the parent element;
330 * 4. the name of this element;
331 * 5. all ElementCollectors working on this BufferNode;
332 * 6. the Blocker working on this BufferNode;
333 * 7. all child BufferNodes' information.
336 * pBufferNode - the BufferNode from where information will be retrieved.
337 * nIndent - how many space characters prefixed before the output
341 * info - the information string
345 * Email: michael.mi@sun.com
346 ******************************************************************************/
350 for ( int i
=0; i
<nIndent
; ++i
)
352 rc
+= OUString( " " );
355 if (pBufferNode
== m_pCurrentBufferNode
)
357 rc
+= OUString( "[%]" );
360 if (pBufferNode
== m_pCurrentBlockingBufferNode
)
362 rc
+= OUString( "[B]" );
365 rc
+= OUString( " " );
366 rc
+= m_xXMLDocument
->getNodeName(pBufferNode
->getXMLElement());
368 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
371 rc
+= OUString( "[" );
372 rc
+= m_xXMLDocument
->getNodeName(pParent
->getXMLElement());
373 rc
+= OUString( "]" );
376 rc
+= OUString( ":EC=" );
377 rc
+= pBufferNode
->printChildren();
378 rc
+= OUString( " BR=" );
380 ElementMark
* pBlocker
= pBufferNode
->getBlocker();
381 if (pBlocker
!= NULL
)
383 rc
+= OUString::number( pBlocker
->getBufferId() );
384 rc
+= OUString( "(SecId=" );
385 rc
+= OUString::number( pBlocker
->getSecurityId() );
386 rc
+= OUString( ")" );
387 rc
+= OUString( " " );
389 rc
+= OUString( "\n" );
391 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
392 std::vector
< const BufferNode
* >::const_iterator jj
= vChildren
->begin();
393 for( ; jj
!= vChildren
->end(); ++jj
)
395 rc
+= printBufferNode(const_cast<BufferNode
*>(*jj
), nIndent
+4);
403 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
404 SAXEventKeeperImpl::collectChildWorkingElement(BufferNode
* pBufferNode
)
405 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
408 * collectChildWorkingElement -- collects a BufferNode's all child
412 * list = collectChildWorkingElement( pBufferNode );
418 * pBufferNode - the BufferNode whose child Elements will be collected.
421 * list - the child Elements list.
425 * Email: michael.mi@sun.com
426 ******************************************************************************/
428 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
430 cssu::Sequence
< cssu::Reference
<
431 cssxw::XXMLElementWrapper
> > aChildrenCollection ( vChildren
->size());
433 std::vector
< const BufferNode
* >::const_iterator ii
= vChildren
->begin();
435 sal_Int32 nIndex
= 0;
436 for( ; ii
!= vChildren
->end(); ++ii
)
438 aChildrenCollection
[nIndex
] = (*ii
)->getXMLElement();
444 return aChildrenCollection
;
447 void SAXEventKeeperImpl::smashBufferNode(
448 BufferNode
* pBufferNode
, bool bClearRoot
) const
449 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
452 * smashBufferNode -- removes a BufferNode along with its working
456 * smashBufferNode( pBufferNode, bClearRoot );
459 * removes the BufferNode's working element from the DOM document, while
460 * reserves all ancestor paths for its child BufferNodes.
461 * when any of the BufferNode's ancestor element is useless, removes it
463 * removes the BufferNode from the BufferNode tree.
466 * pBufferNode - the BufferNode to be removed
467 * bClearRoot - whether the root element also needs to be cleared up.
473 * when removeing a Blocker's BufferNode, the bClearRoot flag should be
474 * true. Because a Blocker can buffer many SAX events which are not used
475 * by any other ElementCollector or Blocker.
476 * When the bClearRoot is set to true, the root BufferNode will be first
477 * cleared, with a stop flag seting at the next Blocking BufferNode. This
478 * operation can delete all useless bufferred SAX events which are only
479 * needed by the Blocker to be deleted.
483 * Email: michael.mi@sun.com
484 ******************************************************************************/
486 if (!pBufferNode
->hasAnything())
488 BufferNode
* pParent
= const_cast<BufferNode
*>(pBufferNode
->getParent());
491 * delete the XML data
493 if (pParent
== m_pRootBufferNode
)
495 bool bIsNotBlocking
= (m_pCurrentBlockingBufferNode
== NULL
);
496 bool bIsBlockInside
= false;
497 bool bIsBlockingAfterward
= false;
500 * If this is a blocker, then remove any out-element data
501 * which caused by blocking. The removal process will stop
502 * at the next blokcer to avoid removing any useful data.
506 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
507 aChildElements
= collectChildWorkingElement(m_pRootBufferNode
);
510 * the clearUselessData only clearup the content in the
511 * node, not the node itself.
513 m_xXMLDocument
->clearUselessData(m_pRootBufferNode
->getXMLElement(),
515 bIsNotBlocking
?(NULL
):
516 (m_pCurrentBlockingBufferNode
->getXMLElement()));
519 * remove the node if it is empty, then if its parent is also
520 * empty, remove it, then if the next parent is also empty,
521 * remove it,..., until parent become null.
523 m_xXMLDocument
->collapse( m_pRootBufferNode
->getXMLElement() );
527 * if blocking, check the relationship between this BufferNode and
528 * the current blocking BufferNode.
530 if ( !bIsNotBlocking
)
533 * the current blocking BufferNode is a descendant of this BufferNode.
535 bIsBlockInside
= (NULL
!= pBufferNode
->isAncestor(m_pCurrentBlockingBufferNode
));
538 * the current blocking BufferNode locates behind this BufferNode in tree
541 bIsBlockingAfterward
= pBufferNode
->isPrevious(m_pCurrentBlockingBufferNode
);
545 * this BufferNode's working element needs to be deleted only when
546 * 1. there is no blocking, or
547 * 2. the current blocking BufferNode is a descendant of this BufferNode,
548 * (then in the BufferNode's working element, the useless data before the blocking
549 * element should be deleted.) or
550 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
551 * (then the useless data between the blocking element and the working element
552 * should be deleted.).
553 * Otherwise, this working element should not be deleted.
555 if ( bIsNotBlocking
|| bIsBlockInside
|| bIsBlockingAfterward
)
557 cssu::Sequence
< cssu::Reference
< cssxw::XXMLElementWrapper
> >
558 aChildElements
= collectChildWorkingElement(pBufferNode
);
561 * the clearUselessData only clearup the content in the
562 * node, not the node itself.
564 m_xXMLDocument
->clearUselessData(pBufferNode
->getXMLElement(),
566 bIsBlockInside
?(m_pCurrentBlockingBufferNode
->getXMLElement()):
570 * remove the node if it is empty, then if its parent is also
571 * empty, remove it, then if the next parent is also empty,
572 * remove it,..., until parent become null.
574 m_xXMLDocument
->collapse( pBufferNode
->getXMLElement() );
578 sal_Int32 nIndex
= pParent
->indexOfChild(pBufferNode
);
580 std::vector
< const BufferNode
* >* vChildren
= pBufferNode
->getChildren();
581 pParent
->removeChild(pBufferNode
);
582 pBufferNode
->setParent(NULL
);
584 std::vector
< const BufferNode
* >::const_iterator ii
= vChildren
->begin();
585 for( ; ii
!= vChildren
->end(); ++ii
)
587 const_cast<BufferNode
*>(*ii
)->setParent(pParent
);
588 pParent
->addChild(*ii
, nIndex
);
595 * delete the BufferNode
601 BufferNode
* SAXEventKeeperImpl::findNextBlockingBufferNode(
602 BufferNode
* pStartBufferNode
)
603 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
606 * findNextBlockingBufferNode -- finds the next blocking BufferNode
607 * behind the particular BufferNode.
610 * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
616 * pStartBufferNode - the BufferNode from where to search the next
617 * blocking BufferNode.
620 * pBufferNode - the next blocking BufferNode, or NULL if no such
625 * Email: michael.mi@sun.com
626 ******************************************************************************/
628 BufferNode
* pNext
= NULL
;
630 if (pStartBufferNode
!= NULL
)
632 pNext
= pStartBufferNode
;
634 while (NULL
!= (pNext
= const_cast<BufferNode
*>(pNext
->getNextNodeByTreeOrder())))
636 if (pNext
->getBlocker() != NULL
)
646 void SAXEventKeeperImpl::diffuse(BufferNode
* pBufferNode
)
647 /****** SAXEventKeeperImpl/diffuse *******************************************
650 * diffuse -- diffuse the notification.
653 * diffuse( pBufferNode );
656 * diffuse the collecting completion notification from the specific
657 * BufferNode along its parent link, until an ancestor which is not
658 * completely received is met.
661 * pBufferNode - the BufferNode from which the notification will be
669 * Email: michael.mi@sun.com
670 ******************************************************************************/
672 BufferNode
* pParent
= pBufferNode
;
674 while(pParent
->isAllReceived())
676 pParent
->elementCollectorNotify();
677 pParent
= const_cast<BufferNode
*>(pParent
->getParent());
681 void SAXEventKeeperImpl::releaseElementMarkBuffer()
682 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
685 * releaseElementMarkBuffer -- releases useless ElementMarks
688 * releaseElementMarkBuffer( );
691 * releases each ElementMark in the releasing list
692 * m_vReleasedElementMarkBuffers.
693 * The operation differs between an ElementCollector and a Blocker.
703 * Email: michael.mi@sun.com
704 ******************************************************************************/
706 m_bIsReleasing
= true;
707 while (!m_vReleasedElementMarkBuffers
.empty())
709 std::vector
< sal_Int32
>::iterator pId
= m_vReleasedElementMarkBuffers
.begin();
710 sal_Int32 nId
= *pId
;
711 m_vReleasedElementMarkBuffers
.erase( pId
);
713 ElementMark
* pElementMark
= findElementMarkBuffer(nId
);
715 if (pElementMark
!= NULL
)
717 if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
718 == pElementMark
->getType())
723 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(pElementMark
);
725 cssxc::sax::ElementMarkPriority nPriority
= pElementCollector
->getPriority();
727 * Delete the EC from the buffer node.
729 BufferNode
* pBufferNode
= pElementCollector
->getBufferNode();
730 pBufferNode
->removeElementCollector(pElementCollector
);
732 if ( nPriority
== cssxc::sax::ElementMarkPriority_BEFOREMODIFY
)
734 pBufferNode
->notifyBranch();
738 * delete the ElementMark
740 pElementCollector
= NULL
;
742 removeElementMarkBuffer(nId
);
745 * delete the BufferNode
747 diffuse(pBufferNode
);
748 smashBufferNode(pBufferNode
, false);
756 * Delete the TH from the buffer node.
758 BufferNode
*pBufferNode
= pElementMark
->getBufferNode();
759 pBufferNode
->setBlocker(NULL
);
762 * If there is a following handler and no blocking now, then
765 if (m_pCurrentBlockingBufferNode
== pBufferNode
)
768 * Before forwarding, the next blocking point needs to be
771 m_pCurrentBlockingBufferNode
= findNextBlockingBufferNode(pBufferNode
);
774 * Forward the blocked events between these two STHs.
776 if (m_xNextHandler
.is())
778 BufferNode
* pTempCurrentBufferNode
= m_pCurrentBufferNode
;
779 BufferNode
* pTempCurrentBlockingBufferNode
= m_pCurrentBlockingBufferNode
;
781 m_pCurrentBufferNode
= pBufferNode
;
782 m_pCurrentBlockingBufferNode
= NULL
;
784 m_bIsForwarding
= true;
786 m_xXMLDocument
->generateSAXEvents(
789 pBufferNode
->getXMLElement(),
790 (pTempCurrentBlockingBufferNode
== NULL
)?NULL
:(pTempCurrentBlockingBufferNode
->getXMLElement()));
792 m_bIsForwarding
= false;
794 m_pCurrentBufferNode
= pTempCurrentBufferNode
;
795 if (m_pCurrentBlockingBufferNode
== NULL
)
797 m_pCurrentBlockingBufferNode
= pTempCurrentBlockingBufferNode
;
801 if (m_pCurrentBlockingBufferNode
== NULL
&&
802 m_xSAXEventKeeperStatusChangeListener
.is())
804 m_xSAXEventKeeperStatusChangeListener
->blockingStatusChanged(sal_False
);
809 * delete the ElementMark
812 removeElementMarkBuffer(nId
);
815 * delete the BufferNode
817 diffuse(pBufferNode
);
818 smashBufferNode(pBufferNode
, true);
823 m_bIsReleasing
= false;
825 if (!m_pRootBufferNode
->hasAnything() &&
826 !m_pRootBufferNode
->hasChildren() &&
827 m_xSAXEventKeeperStatusChangeListener
.is())
829 m_xSAXEventKeeperStatusChangeListener
->bufferStatusChanged(sal_True
);
833 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId
)
834 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
837 * markElementMarkBuffer -- marks an ElementMark to be released
840 * markElementMarkBuffer( nId );
843 * puts the ElementMark with the particular Id into the releasing list,
844 * checks whether the releasing process is running, if not then launch
848 * nId - the Id of the ElementMark which will be released
855 * Email: michael.mi@sun.com
856 ******************************************************************************/
858 m_vReleasedElementMarkBuffers
.push_back( nId
);
859 if ( !m_bIsReleasing
)
861 releaseElementMarkBuffer();
865 sal_Int32
SAXEventKeeperImpl::createElementCollector(
866 sal_Int32 nSecurityId
,
867 cssxc::sax::ElementMarkPriority nPriority
,
869 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& xReferenceResolvedListener
)
870 /****** SAXEventKeeperImpl/createElementCollector ****************************
873 * createElementCollector -- creates a new ElementCollector on the
877 * nId = createElementCollector( nSecurityId, nPriority,
879 * xReferenceResolvedListener );
882 * allocs a new Id, then create an ElementCollector with this Id value.
883 * Add the new created ElementCollector to the new ElementCollecotor list.
886 * nSecurityId - the security Id of the new ElementCollector
887 * nPriority - the prirority of the new ElementCollector
888 * bModifyElement -whether this BufferNode will modify the content of
889 * the corresponding element it works on
890 * xReferenceResolvedListener - the listener for the new ElementCollector.
893 * nId - the Id of the new ElementCollector
897 * Email: michael.mi@sun.com
898 ******************************************************************************/
900 sal_Int32 nId
= m_nNextElementMarkId
;
901 m_nNextElementMarkId
++;
903 ElementCollector
* pElementCollector
904 = new ElementCollector(
909 xReferenceResolvedListener
);
911 m_vElementMarkBuffers
.push_back( pElementCollector
);
914 * All the new EC to initial EC array.
916 m_vNewElementCollectors
.push_back( pElementCollector
);
922 sal_Int32
SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId
)
923 /****** SAXEventKeeperImpl/createBlocker *************************************
926 * createBlocker -- creates a new Blocker on the incoming element.
929 * nId = createBlocker( nSecurityId );
935 * nSecurityId - the security Id of the new Blocker
938 * nId - the Id of the new Blocker
942 * Email: michael.mi@sun.com
943 ******************************************************************************/
945 sal_Int32 nId
= m_nNextElementMarkId
;
946 m_nNextElementMarkId
++;
948 OSL_ASSERT(m_pNewBlocker
== NULL
);
950 m_pNewBlocker
= new ElementMark(nSecurityId
, nId
);
951 m_vElementMarkBuffers
.push_back( m_pNewBlocker
);
956 /* XSAXEventKeeper */
957 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addElementCollector( )
958 throw (cssu::RuntimeException
, std::exception
)
960 return createElementCollector(
961 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
,
962 cssxc::sax::ElementMarkPriority_AFTERMODIFY
,
967 void SAL_CALL
SAXEventKeeperImpl::removeElementCollector( sal_Int32 id
)
968 throw (cssu::RuntimeException
, std::exception
)
970 markElementMarkBuffer(id
);
973 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addBlocker( )
974 throw (cssu::RuntimeException
, std::exception
)
976 return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
);
979 void SAL_CALL
SAXEventKeeperImpl::removeBlocker( sal_Int32 id
)
980 throw (cssu::RuntimeException
, std::exception
)
982 markElementMarkBuffer(id
);
985 sal_Bool SAL_CALL
SAXEventKeeperImpl::isBlocking( )
986 throw (cssu::RuntimeException
, std::exception
)
988 return (m_pCurrentBlockingBufferNode
!= NULL
);
991 cssu::Reference
< cssxw::XXMLElementWrapper
> SAL_CALL
992 SAXEventKeeperImpl::getElement( sal_Int32 id
)
993 throw (cssu::RuntimeException
, std::exception
)
995 cssu::Reference
< cssxw::XXMLElementWrapper
> rc
;
997 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
998 if (pElementMark
!= NULL
)
1000 rc
= pElementMark
->getBufferNode()->getXMLElement();
1006 void SAL_CALL
SAXEventKeeperImpl::setElement(
1008 const cssu::Reference
< cssxw::XXMLElementWrapper
>& aElement
)
1009 throw (cssu::RuntimeException
, std::exception
)
1013 m_xXMLDocument
->rebuildIDLink(aElement
);
1015 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
1017 if (pElementMark
!= NULL
)
1019 BufferNode
* pBufferNode
= pElementMark
->getBufferNode();
1020 if (pBufferNode
!= NULL
)
1022 bool bIsCurrent
= m_xXMLDocument
->isCurrent(pBufferNode
->getXMLElement());
1023 pBufferNode
->setXMLElement(aElement
);
1027 m_xXMLDocument
->setCurrentElement(aElement
);
1034 removeElementCollector( id
);
1038 cssu::Reference
< cssxs::XDocumentHandler
> SAL_CALL
SAXEventKeeperImpl::setNextHandler(
1039 const cssu::Reference
< cssxs::XDocumentHandler
>& xNewHandler
)
1040 throw (cssu::RuntimeException
, std::exception
)
1042 cssu::Reference
< cssxs::XDocumentHandler
> xOldHandler
= m_xNextHandler
;
1044 m_xNextHandler
= xNewHandler
;
1048 OUString SAL_CALL
SAXEventKeeperImpl::printBufferNodeTree()
1049 throw (cssu::RuntimeException
, std::exception
)
1053 rc
+= OUString( "ElementMarkBuffers: size = " );
1054 rc
+= OUString::number(m_vElementMarkBuffers
.size());
1055 rc
+= OUString( "\nCurrentBufferNode: " );
1056 rc
+= m_xXMLDocument
->getNodeName(m_pCurrentBufferNode
->getXMLElement());
1057 rc
+= OUString( "\n" );
1058 rc
+= printBufferNode(m_pRootBufferNode
, 0);
1063 cssu::Reference
< cssxw::XXMLElementWrapper
> SAL_CALL
SAXEventKeeperImpl::getCurrentBlockingNode()
1064 throw (cssu::RuntimeException
, std::exception
)
1066 cssu::Reference
< cssxw::XXMLElementWrapper
> rc
;
1068 if (m_pCurrentBlockingBufferNode
!= NULL
)
1070 rc
= m_pCurrentBlockingBufferNode
->getXMLElement();
1076 /* XSecuritySAXEventKeeper */
1077 sal_Int32 SAL_CALL
SAXEventKeeperImpl::addSecurityElementCollector(
1078 cssxc::sax::ElementMarkPriority priority
,
1079 sal_Bool modifyElement
)
1080 throw (cssu::RuntimeException
, std::exception
)
1082 return createElementCollector(
1083 cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID
,
1089 sal_Int32 SAL_CALL
SAXEventKeeperImpl::cloneElementCollector(
1090 sal_Int32 referenceId
,
1091 cssxc::sax::ElementMarkPriority priority
)
1092 throw (cssu::RuntimeException
, std::exception
)
1096 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(findElementMarkBuffer(referenceId
));
1097 if (pElementCollector
!= NULL
)
1099 nId
= m_nNextElementMarkId
;
1100 m_nNextElementMarkId
++;
1102 ElementCollector
* pClonedOne
1103 = pElementCollector
->clone(nId
, priority
);
1106 * add this EC into the security data buffer array.
1108 m_vElementMarkBuffers
.push_back(pClonedOne
);
1111 * If the reference EC is still in initial EC array, add
1112 * this cloned one into the initial EC array too.
1114 if (pElementCollector
->getBufferNode() == NULL
)
1116 m_vNewElementCollectors
.push_back(pClonedOne
);
1123 void SAL_CALL
SAXEventKeeperImpl::setSecurityId( sal_Int32 id
, sal_Int32 securityId
)
1124 throw (cssu::RuntimeException
, std::exception
)
1126 ElementMark
* pElementMark
= findElementMarkBuffer(id
);
1127 if (pElementMark
!= NULL
)
1129 pElementMark
->setSecurityId(securityId
);
1134 /* XReferenceResolvedBroadcaster */
1135 void SAL_CALL
SAXEventKeeperImpl::addReferenceResolvedListener(
1136 sal_Int32 referenceId
,
1137 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>& listener
)
1138 throw (cssu::RuntimeException
, std::exception
)
1140 ElementCollector
* pElementCollector
= static_cast<ElementCollector
*>(findElementMarkBuffer(referenceId
));
1141 if (pElementCollector
!= NULL
)
1143 pElementCollector
->setReferenceResolvedListener(listener
);
1147 void SAL_CALL
SAXEventKeeperImpl::removeReferenceResolvedListener(
1148 sal_Int32
/*referenceId*/,
1149 const cssu::Reference
< cssxc::sax::XReferenceResolvedListener
>&)
1150 throw (cssu::RuntimeException
, std::exception
)
1154 /* XSAXEventKeeperStatusChangeBroadcaster */
1155 void SAL_CALL
SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1156 const cssu::Reference
< cssxc::sax::XSAXEventKeeperStatusChangeListener
>& listener
)
1157 throw (cssu::RuntimeException
, std::exception
)
1159 m_xSAXEventKeeperStatusChangeListener
= listener
;
1162 void SAL_CALL
SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1163 const cssu::Reference
< cssxc::sax::XSAXEventKeeperStatusChangeListener
>&)
1164 throw (cssu::RuntimeException
, std::exception
)
1168 /* XDocumentHandler */
1169 void SAL_CALL
SAXEventKeeperImpl::startDocument( )
1170 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1172 if ( m_xNextHandler
.is())
1174 m_xNextHandler
->startDocument();
1178 void SAL_CALL
SAXEventKeeperImpl::endDocument( )
1179 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1181 if ( m_xNextHandler
.is())
1183 m_xNextHandler
->endDocument();
1187 void SAL_CALL
SAXEventKeeperImpl::startElement(
1188 const OUString
& aName
,
1189 const cssu::Reference
< cssxs::XAttributeList
>& xAttribs
)
1190 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1193 * If there is a following handler and no blocking now, then
1194 * forward this event
1196 if ((m_pCurrentBlockingBufferNode
== NULL
) &&
1197 (m_xNextHandler
.is()) &&
1198 (!m_bIsForwarding
) &&
1199 (m_pNewBlocker
== NULL
))
1201 m_xNextHandler
->startElement(aName
, xAttribs
);
1205 * If not forwarding, buffer this startElement.
1207 if (!m_bIsForwarding
)
1209 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1210 m_xDocumentHandler
->startElement(aName
, xAttribs
);
1212 sal_Int32 nLength
= xAttribs
->getLength();
1213 cssu::Sequence
< cssxcsax::XMLAttribute
> aAttributes (nLength
);
1215 for ( int i
= 0; i
<nLength
; ++i
)
1217 aAttributes
[i
].sName
= xAttribs
->getNameByIndex((short)i
);
1218 aAttributes
[i
].sValue
=xAttribs
->getValueByIndex((short)i
);
1221 m_xCompressedDocumentHandler
->compressedStartElement(aName
, aAttributes
);
1226 BufferNode
* pBufferNode
= addNewElementMarkBuffers();
1227 if (pBufferNode
!= NULL
)
1229 setCurrentBufferNode(pBufferNode
);
1233 void SAL_CALL
SAXEventKeeperImpl::endElement( const OUString
& aName
)
1234 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1236 bool bIsCurrent
= m_xXMLDocument
->isCurrent(m_pCurrentBufferNode
->getXMLElement());
1239 * If there is a following handler and no blocking now, then
1240 * forward this event
1242 if ((m_pCurrentBlockingBufferNode
== NULL
) &&
1243 (m_xNextHandler
.is()) &&
1246 m_xNextHandler
->endElement(aName
);
1249 if ((m_pCurrentBlockingBufferNode
!= NULL
) ||
1250 (m_pCurrentBufferNode
!= m_pRootBufferNode
) ||
1251 (!m_xXMLDocument
->isCurrentElementEmpty()))
1253 if (!m_bIsForwarding
)
1255 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1256 m_xDocumentHandler
->endElement(aName
);
1258 m_xCompressedDocumentHandler
->compressedEndElement(aName
);
1263 * If the current buffer node has not notified yet, and
1264 * the current buffer node is waiting for the current element,
1265 * then let it notify.
1267 if (bIsCurrent
&& (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1269 BufferNode
* pOldCurrentBufferNode
= m_pCurrentBufferNode
;
1270 m_pCurrentBufferNode
= const_cast<BufferNode
*>(m_pCurrentBufferNode
->getParent());
1272 pOldCurrentBufferNode
->setReceivedAll();
1274 if ((m_pCurrentBufferNode
== m_pRootBufferNode
) &&
1275 m_xSAXEventKeeperStatusChangeListener
.is())
1277 m_xSAXEventKeeperStatusChangeListener
->collectionStatusChanged(sal_False
);
1283 if (!m_bIsForwarding
)
1285 m_xXMLDocument
->removeCurrentElement();
1290 void SAL_CALL
SAXEventKeeperImpl::characters( const OUString
& aChars
)
1291 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1293 if (!m_bIsForwarding
)
1295 if ((m_pCurrentBlockingBufferNode
== NULL
) && m_xNextHandler
.is())
1297 m_xNextHandler
->characters(aChars
);
1300 if ((m_pCurrentBlockingBufferNode
!= NULL
) ||
1301 (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1303 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1304 m_xDocumentHandler
->characters(aChars
);
1306 m_xCompressedDocumentHandler
->compressedCharacters(aChars
);
1312 void SAL_CALL
SAXEventKeeperImpl::ignorableWhitespace( const OUString
& aWhitespaces
)
1313 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1315 characters( aWhitespaces
);
1318 void SAL_CALL
SAXEventKeeperImpl::processingInstruction(
1319 const OUString
& aTarget
, const OUString
& aData
)
1320 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1322 if (!m_bIsForwarding
)
1324 if ((m_pCurrentBlockingBufferNode
== NULL
) && m_xNextHandler
.is())
1326 m_xNextHandler
->processingInstruction(aTarget
, aData
);
1329 if ((m_pCurrentBlockingBufferNode
!= NULL
) ||
1330 (m_pCurrentBufferNode
!= m_pRootBufferNode
))
1332 #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1333 m_xDocumentHandler
->processingInstruction(aTarget
, aData
);
1335 m_xCompressedDocumentHandler
->compressedProcessingInstruction(aTarget
, aData
);
1341 void SAL_CALL
SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference
< cssxs::XLocator
>&)
1342 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
1346 /* XInitialization */
1347 void SAL_CALL
SAXEventKeeperImpl::initialize( const cssu::Sequence
< cssu::Any
>& aArguments
)
1348 throw (cssu::Exception
, cssu::RuntimeException
, std::exception
)
1350 OSL_ASSERT(aArguments
.getLength() == 1);
1352 aArguments
[0] >>= m_xXMLDocument
;
1353 m_xDocumentHandler
= cssu::Reference
< cssxs::XDocumentHandler
>(
1354 m_xXMLDocument
, cssu::UNO_QUERY
);
1355 m_xCompressedDocumentHandler
= cssu::Reference
< cssxcsax::XCompressedDocumentHandler
>(
1356 m_xXMLDocument
, cssu::UNO_QUERY
);
1358 m_pRootBufferNode
= new BufferNode(m_xXMLDocument
->getCurrentElement());
1359 m_pCurrentBufferNode
= m_pRootBufferNode
;
1362 OUString
SAXEventKeeperImpl_getImplementationName ()
1363 throw (cssu::RuntimeException
)
1365 return OUString ( IMPLEMENTATION_NAME
);
1368 cssu::Sequence
< OUString
> SAL_CALL
SAXEventKeeperImpl_getSupportedServiceNames( )
1369 throw (cssu::RuntimeException
)
1371 cssu::Sequence
< OUString
> aRet(1);
1372 OUString
* pArray
= aRet
.getArray();
1373 pArray
[0] = "com.sun.star.xml.crypto.sax.SAXEventKeeper";
1377 cssu::Reference
< cssu::XInterface
> SAL_CALL
SAXEventKeeperImpl_createInstance(
1378 const cssu::Reference
< cssl::XMultiServiceFactory
> &)
1379 throw( cssu::Exception
)
1381 return (cppu::OWeakObject
*) new SAXEventKeeperImpl();
1385 OUString SAL_CALL
SAXEventKeeperImpl::getImplementationName( )
1386 throw (cssu::RuntimeException
, std::exception
)
1388 return SAXEventKeeperImpl_getImplementationName();
1391 sal_Bool SAL_CALL
SAXEventKeeperImpl::supportsService( const OUString
& rServiceName
)
1392 throw (cssu::RuntimeException
, std::exception
)
1394 return cppu::supportsService(this, rServiceName
);
1397 cssu::Sequence
< OUString
> SAL_CALL
SAXEventKeeperImpl::getSupportedServiceNames( )
1398 throw (cssu::RuntimeException
, std::exception
)
1400 return SAXEventKeeperImpl_getSupportedServiceNames();
1403 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */