xref: /AOO41X/main/xmlsecurity/source/framework/saxeventkeeperimpl.cxx (revision 06b3ce531745799678cf4bb887ef37436d81238b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmlsecurity.hxx"
26 
27 #include "saxeventkeeperimpl.hxx"
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
30 #include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
31 
32 namespace cssu = com::sun::star::uno;
33 namespace cssl = com::sun::star::lang;
34 namespace cssxc = com::sun::star::xml::crypto;
35 namespace cssxcsax = com::sun::star::xml::csax;
36 namespace cssxw = com::sun::star::xml::wrapper;
37 namespace cssxs = com::sun::star::xml::sax;
38 
39 #define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
40 #define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
41 
42 #define _USECOMPRESSEDDOCUMENTHANDLER
43 
SAXEventKeeperImpl()44 SAXEventKeeperImpl::SAXEventKeeperImpl( )
45     :m_pRootBufferNode(NULL),
46      m_pCurrentBufferNode(NULL),
47      m_nNextElementMarkId(1),
48      m_pNewBlocker(NULL),
49      m_pCurrentBlockingBufferNode(NULL),
50      m_bIsReleasing(false),
51      m_bIsForwarding(false)
52 {
53     m_vElementMarkBuffers.reserve(2);
54     m_vNewElementCollectors.reserve(2);
55     m_vReleasedElementMarkBuffers.reserve(2);
56 }
57 
~SAXEventKeeperImpl()58 SAXEventKeeperImpl::~SAXEventKeeperImpl()
59 {
60     /*
61      * delete the BufferNode tree
62      */
63     if (m_pRootBufferNode != NULL)
64     {
65         m_pRootBufferNode->freeAllChildren();
66         delete m_pRootBufferNode;
67     }
68 
69     m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
70 
71     /*
72      * delete all unfreed ElementMarks
73      */
74     m_vNewElementCollectors.clear();
75     m_pNewBlocker = NULL;
76 
77     std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
78     for( ; ii != m_vElementMarkBuffers.end(); ++ii )
79     {
80         delete (*ii);
81     }
82     m_vElementMarkBuffers.clear();
83 }
84 
setCurrentBufferNode(BufferNode * pBufferNode)85 void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
86 /****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
87  *
88  *   NAME
89  *  setCurrentBufferNode -- set a new active BufferNode.
90  *
91  *   SYNOPSIS
92  *  setCurrentBufferNode( pBufferNode );
93  *
94  *   FUNCTION
95  *  connects this BufferNode into the BufferNode tree as a child of the
96  *  current active BufferNode. Then makes this BufferNode as the current
97  *  active BufferNode.
98  *  If the previous active BufferNode points to the root
99  *  BufferNode, which means that no buffering operation was proceeding,
100  *  then notifies the status change listener that buffering  operation
101  *  will begin at once.
102  *
103  *   INPUTS
104  *  pBufferNode - a BufferNode which will be the new active BufferNode
105  *
106  *   RESULT
107  *  empty
108  *
109  *   HISTORY
110  *  05.01.2004 -    implemented
111  *
112  *   AUTHOR
113  *  Michael Mi
114  *  Email: michael.mi@sun.com
115  ******************************************************************************/
116 {
117     if (pBufferNode != m_pCurrentBufferNode)
118     {
119         if ( m_pCurrentBufferNode == m_pRootBufferNode &&
120              m_xSAXEventKeeperStatusChangeListener.is())
121         {
122             m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
123         }
124 
125         if (pBufferNode->getParent() == NULL)
126         {
127             m_pCurrentBufferNode->addChild(pBufferNode);
128             pBufferNode->setParent(m_pCurrentBufferNode);
129         }
130 
131         m_pCurrentBufferNode = pBufferNode;
132     }
133 }
134 
addNewElementMarkBuffers()135 BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
136 /****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
137  *
138  *   NAME
139  *  addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
140  *
141  *   SYNOPSIS
142  *  pBufferNode = addNewElementMarkBuffers( );
143  *
144  *   FUNCTION
145  *  if there are new ElementCollector or new Blocker to be added, then
146  *  connect all of them with the current BufferNode. In case of the
147  *  current BufferNode doesn't exist, creates one.
148  *  Clears up the new ElementCollector list and the new Blocker pointer.
149  *
150  *   INPUTS
151  *  empty
152  *
153  *   RESULT
154  *  pBufferNode - the BufferNode that has been connected with both new
155  *                ElementCollectors and new Blocker.
156  *
157  *   HISTORY
158  *  05.01.2004 -    implemented
159  *
160  *   AUTHOR
161  *  Michael Mi
162  *  Email: michael.mi@sun.com
163  ******************************************************************************/
164 {
165     BufferNode* pBufferNode = NULL;
166 
167     if ( (m_vNewElementCollectors.size()>0) ||
168          (m_pNewBlocker != NULL))
169     {
170         /*
171          * When the current BufferNode is right pointing to the current
172          * working element in the XMLDocumentWrapper component, then
173          * no new BufferNode is needed to create.
174          * This situation can only happen in the "Forwarding" mode.
175          */
176         if ( (m_pCurrentBufferNode != NULL) &&
177              (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
178         {
179             pBufferNode = m_pCurrentBufferNode;
180         }
181         else
182         {
183             pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
184         }
185 
186         if (m_pNewBlocker != NULL)
187         {
188             pBufferNode->setBlocker(m_pNewBlocker);
189 
190             /*
191              * If no blocking before, then notify the status change listener that
192              * the SAXEventKeeper has entered "blocking" status, during which, no
193              * SAX events will be forwarded to the next document handler.
194              */
195             if (m_pCurrentBlockingBufferNode == NULL)
196             {
197                 m_pCurrentBlockingBufferNode = pBufferNode;
198 
199                 if (m_xSAXEventKeeperStatusChangeListener.is())
200                 {
201                     m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
202                 }
203             }
204 
205             m_pNewBlocker = NULL;
206         }
207 
208         if (m_vNewElementCollectors.size()>0)
209         {
210             std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
211 
212             for( ; ii != m_vNewElementCollectors.end(); ++ii )
213             {
214                 pBufferNode->addElementCollector(*ii);
215             }
216 
217             m_vNewElementCollectors.clear();
218         }
219     }
220 
221     return pBufferNode;
222 }
223 
findElementMarkBuffer(sal_Int32 nId) const224 ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
225 /****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
226  *
227  *   NAME
228  *  findElementMarkBuffer -- finds an ElementMark.
229  *
230  *   SYNOPSIS
231  *  pElementMark = findElementMarkBuffer( nId );
232  *
233  *   FUNCTION
234  *  searches an ElementMark with the particular Id in the ElementMark
235  *  list.
236  *
237  *   INPUTS
238  *  nId - the Id of the ElementMark to be searched.
239  *
240  *   RESULT
241  *  pElementMark - the ElementMark with the particular Id, or NULL when
242  *                 no such Id exists.
243  *
244  *   HISTORY
245  *  05.01.2004 -    implemented
246  *
247  *   AUTHOR
248  *  Michael Mi
249  *  Email: michael.mi@sun.com
250  ******************************************************************************/
251 {
252     ElementMark* pElementMark = NULL;
253 
254     std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
255 
256     for( ; ii != m_vElementMarkBuffers.end(); ++ii )
257     {
258         if ( nId == (*ii)->getBufferId())
259         {
260             pElementMark = (ElementMark*)*ii;
261             break;
262         }
263     }
264 
265     return pElementMark;
266 }
267 
removeElementMarkBuffer(sal_Int32 nId)268 void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
269 /****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
270  *
271  *   NAME
272  *  removeElementMarkBuffer -- removes an ElementMark
273  *
274  *   SYNOPSIS
275  *  removeElementMarkBuffer( nId );
276  *
277  *   FUNCTION
278  *  removes an ElementMark with the particular Id in the ElementMark list.
279  *
280  *   INPUTS
281  *  nId - the Id of the ElementMark to be removed.
282  *
283  *   RESULT
284  *  empty
285  *
286  *   HISTORY
287  *  05.01.2004 -    implemented
288  *
289  *   AUTHOR
290  *  Michael Mi
291  *  Email: michael.mi@sun.com
292  ******************************************************************************/
293 {
294     std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
295 
296     for( ; ii != m_vElementMarkBuffers.end(); ++ii )
297     {
298         if ( nId == (*ii)->getBufferId())
299         {
300             /*
301              * checks whether this ElementMark still in the new ElementCollect array
302              */
303             std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
304             for( ; jj != m_vNewElementCollectors.end(); ++jj )
305             {
306                 if ((*ii) == (*jj))
307                 {
308                     m_vNewElementCollectors.erase(jj);
309                     break;
310                 }
311             }
312 
313             /*
314              * checks whether this ElementMark is the new Blocker
315              */
316             if ((*ii) == m_pNewBlocker)
317             {
318                 m_pNewBlocker = NULL;
319             }
320 
321             /*
322              * destory the ElementMark
323              */
324             delete (*ii);
325 
326             m_vElementMarkBuffers.erase( ii );
327             break;
328         }
329     }
330 }
331 
printBufferNode(BufferNode * pBufferNode,sal_Int32 nIndent) const332 rtl::OUString SAXEventKeeperImpl::printBufferNode(
333     BufferNode* pBufferNode, sal_Int32 nIndent) const
334 /****** SAXEventKeeperImpl/printBufferNode ***********************************
335  *
336  *   NAME
337  *  printBufferNode -- retrieves the information of a BufferNode and its
338  *  branch.
339  *
340  *   SYNOPSIS
341  *  info = printBufferNode( pBufferNode, nIndent );
342  *
343  *   FUNCTION
344  *  all retrieved information includes:
345  *  1. whether it is the current BufferNode;
346  *  2. whether it is the current blocking BufferNode;
347  *  3. the name of the parent element;
348  *  4. the name of this element;
349  *  5. all ElementCollectors working on this BufferNode;
350  *  6. the Blocker working on this BufferNode;
351  *  7. all child BufferNodes' information.
352  *
353  *   INPUTS
354  *  pBufferNode -   the BufferNode from where information will be retrieved.
355  *  nIndent -   how many space characters prefixed before the output
356  *              message.
357  *
358  *   RESULT
359  *  info - the information string
360  *
361  *   HISTORY
362  *  05.01.2004 -    implemented
363  *
364  *   AUTHOR
365  *  Michael Mi
366  *  Email: michael.mi@sun.com
367  ******************************************************************************/
368 {
369     rtl::OUString rc;
370 
371     for ( int i=0; i<nIndent; ++i )
372     {
373         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
374     }
375 
376     if (pBufferNode == m_pCurrentBufferNode)
377     {
378         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
379     }
380 
381     if (pBufferNode == m_pCurrentBlockingBufferNode)
382     {
383         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
384     }
385 
386     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
387     rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
388 
389     BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
390     if (pParent != NULL)
391     {
392         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
393         rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
394         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
395     }
396 
397     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
398     rc += pBufferNode->printChildren();
399     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));
400 
401     ElementMark * pBlocker = pBufferNode->getBlocker();
402     if (pBlocker != NULL)
403     {
404         rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
405         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
406         rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
407         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
408         rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
409     }
410     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
411 
412     std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
413     std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
414     for( ; jj != vChildren->end(); ++jj )
415     {
416         rc += printBufferNode((BufferNode *)*jj, nIndent+4);
417     }
418 
419     delete vChildren;
420 
421     return rc;
422 }
423 
424 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
collectChildWorkingElement(BufferNode * pBufferNode) const425     SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
426 /****** SAXEventKeeperImpl/collectChildWorkingElement ************************
427  *
428  *   NAME
429  *  collectChildWorkingElement -- collects a BufferNode's all child
430  *  Elements.
431  *
432  *   SYNOPSIS
433  *  list = collectChildWorkingElement( pBufferNode );
434  *
435  *   FUNCTION
436  *  see NAME.
437  *
438  *   INPUTS
439  *  pBufferNode - the BufferNode whose child Elements will be collected.
440  *
441  *   RESULT
442  *  list - the child Elements list.
443  *
444  *   HISTORY
445  *  05.01.2004 -    implemented
446  *
447  *   AUTHOR
448  *  Michael Mi
449  *  Email: michael.mi@sun.com
450  ******************************************************************************/
451 {
452     std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
453 
454     cssu::Sequence < cssu::Reference<
455         cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
456 
457     std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
458 
459     sal_Int32 nIndex = 0;
460     for( ; ii != vChildren->end(); ++ii )
461     {
462         aChildrenCollection[nIndex] = (*ii)->getXMLElement();
463         nIndex++;
464     }
465 
466     delete vChildren;
467 
468     return aChildrenCollection;
469 }
470 
smashBufferNode(BufferNode * pBufferNode,bool bClearRoot) const471 void SAXEventKeeperImpl::smashBufferNode(
472     BufferNode* pBufferNode, bool bClearRoot) const
473 /****** SAXEventKeeperImpl/smashBufferNode ***********************************
474  *
475  *   NAME
476  *  smashBufferNode -- removes a BufferNode along with its working
477  *  element.
478  *
479  *   SYNOPSIS
480  *  smashBufferNode( pBufferNode, bClearRoot );
481  *
482  *   FUNCTION
483  *  removes the BufferNode's working element from the DOM document, while
484  *  reserves all ancestor paths for its child BufferNodes.
485  *  when any of the BufferNode's ancestor element is useless, removes it
486  *  too.
487  *  removes the BufferNode from the BufferNode tree.
488  *
489  *   INPUTS
490  *  pBufferNode -   the BufferNode to be removed
491  *  bClearRoot -    whether the root element also needs to be cleared up.
492  *
493  *   RESULT
494  *  empty
495  *
496  *   NOTES
497  *  when removeing a Blocker's BufferNode, the bClearRoot flag should be
498  *  true. Because a Blocker can buffer many SAX events which are not used
499  *  by any other ElementCollector or Blocker.
500  *  When the bClearRoot is set to true, the root BufferNode will be first
501  *  cleared, with a stop flag seting at the next Blocking BufferNode. This
502  *  operation can delete all useless bufferred SAX events which are only
503  *  needed by the Blocker to be deleted.
504  *
505  *   HISTORY
506  *  05.01.2004 -    implemented
507  *
508  *   AUTHOR
509  *  Michael Mi
510  *  Email: michael.mi@sun.com
511  ******************************************************************************/
512 {
513     if (!pBufferNode->hasAnything())
514     {
515         BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
516 
517             /*
518              * delete the XML data
519              */
520         if (pParent == m_pRootBufferNode)
521         {
522             bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
523             bool bIsBlockInside = false;
524             bool bIsBlockingAfterward = false;
525 
526                 /*
527                  * If this is a blocker, then remove any out-element data
528                  * which caused by blocking. The removal process will stop
529                  * at the next blokcer to avoid removing any useful data.
530                  */
531             if (bClearRoot)
532             {
533                 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
534                     aChildElements = collectChildWorkingElement(m_pRootBufferNode);
535 
536                     /*
537                      * the clearUselessData only clearup the content in the
538                      * node, not the node itself.
539                      */
540                 m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
541                     aChildElements,
542                     bIsNotBlocking?(NULL):
543                                    (m_pCurrentBlockingBufferNode->getXMLElement()));
544 
545                     /*
546                      * remove the node if it is empty, then if its parent is also
547                      * empty, remove it, then if the next parent is also empty,
548                      * remove it,..., until parent become null.
549                      */
550                 m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
551             }
552 
553             /*
554              * if blocking, check the relationship between this BufferNode and
555              * the current blocking BufferNode.
556              */
557             if ( !bIsNotBlocking )
558             {
559                 /*
560                  * the current blocking BufferNode is a descendant of this BufferNode.
561                  */
562                 bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
563 
564                 /*
565                  * the current blocking BufferNode locates behind this BufferNode in tree
566                  * order.
567                  */
568                 bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
569             }
570 
571             /*
572              * this BufferNode's working element needs to be deleted only when
573              * 1. there is no blocking, or
574              * 2. the current blocking BufferNode is a descendant of this BufferNode,
575              *    (then in the BufferNode's working element, the useless data before the blocking
576              *     element should be deleted.) or
577              * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
578              *    (then the useless data between the blocking element and the working element
579              *     should be deleted.).
580              * Otherwise, this working element should not be deleted.
581              */
582             if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
583             {
584                 cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
585                     aChildElements = collectChildWorkingElement(pBufferNode);
586 
587                     /*
588                      * the clearUselessData only clearup the content in the
589                      * node, not the node itself.
590                      */
591                 m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
592                     aChildElements,
593                     bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
594                                (NULL));
595 
596                     /*
597                      * remove the node if it is empty, then if its parent is also
598                      * empty, remove it, then if the next parent is also empty,
599                      * remove it,..., until parent become null.
600                      */
601                 m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
602             }
603         }
604 
605         sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
606 
607         std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
608         pParent->removeChild(pBufferNode);
609         pBufferNode->setParent(NULL);
610 
611         std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
612         for( ; ii != vChildren->end(); ++ii )
613         {
614             ((BufferNode *)(*ii))->setParent(pParent);
615             pParent->addChild(*ii, nIndex);
616             nIndex++;
617         }
618 
619         delete vChildren;
620 
621         /*
622          * delete the BufferNode
623          */
624         delete pBufferNode;
625     }
626 }
627 
findNextBlockingBufferNode(BufferNode * pStartBufferNode) const628 BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
629     BufferNode* pStartBufferNode) const
630 /****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
631  *
632  *   NAME
633  *  findNextBlockingBufferNode -- finds the next blocking BufferNode
634  *  behind the particular BufferNode.
635  *
636  *   SYNOPSIS
637  *  pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
638  *
639  *   FUNCTION
640  *  see NAME.
641  *
642  *   INPUTS
643  *  pStartBufferNode - the BufferNode from where to search the next
644  *                     blocking BufferNode.
645  *
646  *   RESULT
647  *  pBufferNode - the next blocking BufferNode, or NULL if no such
648  *                BufferNode exists.
649  *
650  *   HISTORY
651  *  05.01.2004 -    implemented
652  *
653  *   AUTHOR
654  *  Michael Mi
655  *  Email: michael.mi@sun.com
656  ******************************************************************************/
657 {
658     BufferNode* pNext = NULL;
659 
660     if (pStartBufferNode != NULL)
661     {
662         pNext = pStartBufferNode;
663 
664         while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
665         {
666             if (pNext->getBlocker() != NULL)
667             {
668                 break;
669             }
670         }
671     }
672 
673     return pNext;
674 }
675 
diffuse(BufferNode * pBufferNode) const676 void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
677 /****** SAXEventKeeperImpl/diffuse *******************************************
678  *
679  *   NAME
680  *  diffuse -- diffuse the notification.
681  *
682  *   SYNOPSIS
683  *  diffuse( pBufferNode );
684  *
685  *   FUNCTION
686  *  diffuse the collecting completion notification from the specific
687  *  BufferNode along its parent link, until an ancestor which is not
688  *  completely received is met.
689  *
690  *   INPUTS
691  *  pBufferNode - the BufferNode from which the notification will be
692  *                diffused.
693  *
694  *   RESULT
695  *  empty
696  *
697  *   HISTORY
698  *  05.01.2004 -    implemented
699  *
700  *   AUTHOR
701  *  Michael Mi
702  *  Email: michael.mi@sun.com
703  ******************************************************************************/
704 {
705     BufferNode* pParent = pBufferNode;
706 
707     while(pParent->isAllReceived())
708     {
709         pParent->elementCollectorNotify();
710         pParent = (BufferNode*)pParent->getParent();
711     }
712 }
713 
releaseElementMarkBuffer()714 void SAXEventKeeperImpl::releaseElementMarkBuffer()
715 /****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
716  *
717  *   NAME
718  *  releaseElementMarkBuffer -- releases useless ElementMarks
719  *
720  *   SYNOPSIS
721  *  releaseElementMarkBuffer( );
722  *
723  *   FUNCTION
724  *  releases each ElementMark in the releasing list
725  *  m_vReleasedElementMarkBuffers.
726  *  The operation differs between an ElementCollector and a Blocker.
727  *
728  *   INPUTS
729  *  empty
730  *
731  *   RESULT
732  *  empty
733  *
734  *   HISTORY
735  *  05.01.2004 -    implemented
736  *
737  *   AUTHOR
738  *  Michael Mi
739  *  Email: michael.mi@sun.com
740  ******************************************************************************/
741 {
742     m_bIsReleasing = true;
743     while (m_vReleasedElementMarkBuffers.size()>0)
744     {
745         std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
746         sal_Int32 nId = *pId;
747         m_vReleasedElementMarkBuffers.erase( pId );
748 
749         ElementMark* pElementMark = findElementMarkBuffer(nId);
750 
751         if (pElementMark != NULL)
752         {
753             if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
754                 == pElementMark->getType())
755             /*
756              * it is a EC
757              */
758             {
759                 ElementCollector* pElementCollector = (ElementCollector*)pElementMark;
760 
761                 cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
762                 bool bToModify = pElementCollector->getModify();
763 
764                 /*
765                      * Delete the EC from the buffer node.
766                      */
767                 BufferNode* pBufferNode = pElementCollector->getBufferNode();
768                 pBufferNode->removeElementCollector(pElementCollector);
769 
770                 if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
771                 {
772                     pBufferNode->notifyBranch();
773                 }
774 
775                 if (bToModify)
776                 {
777                     pBufferNode->notifyAncestor();
778                 }
779 
780                 /*
781                  * delete the ElementMark
782                  */
783                 pElementCollector = NULL;
784                 pElementMark = NULL;
785                 removeElementMarkBuffer(nId);
786 
787                 /*
788                  * delete the BufferNode
789                  */
790                 diffuse(pBufferNode);
791                 smashBufferNode(pBufferNode, false);
792             }
793             else
794             /*
795              * it is a Blocker
796              */
797             {
798                     /*
799                      * Delete the TH from the buffer node.
800                      */
801                 BufferNode *pBufferNode = pElementMark->getBufferNode();
802                 pBufferNode->setBlocker(NULL);
803 
804                     /*
805                      * If there is a following handler and no blocking now, then
806                      * forward this event
807                      */
808                 if (m_pCurrentBlockingBufferNode == pBufferNode)
809                 {
810                         /*
811                          * Before forwarding, the next blocking point needs to be
812                          * found.
813                          */
814                     m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
815 
816                         /*
817                          * Forward the blocked events between these two STHs.
818                          */
819                         if (m_xNextHandler.is())
820                         {
821                             BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
822                             BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
823 
824                             m_pCurrentBufferNode = pBufferNode;
825                             m_pCurrentBlockingBufferNode = NULL;
826 
827                         m_bIsForwarding = true;
828 
829                         m_xXMLDocument->generateSAXEvents(
830                             m_xNextHandler,
831                             this,
832                             pBufferNode->getXMLElement(),
833                             (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
834 
835                         m_bIsForwarding = false;
836 
837                         m_pCurrentBufferNode = pTempCurrentBufferNode;
838                         if (m_pCurrentBlockingBufferNode == NULL)
839                         {
840                             m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
841                         }
842                     }
843 
844                     if (m_pCurrentBlockingBufferNode == NULL &&
845                         m_xSAXEventKeeperStatusChangeListener.is())
846                     {
847                         m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
848                     }
849                 }
850 
851                 /*
852                  * delete the ElementMark
853                  */
854                 pElementMark = NULL;
855                 removeElementMarkBuffer(nId);
856 
857                 /*
858                  * delete the BufferNode
859                  */
860                 diffuse(pBufferNode);
861                 smashBufferNode(pBufferNode, true);
862             }
863         }
864     }
865 
866     m_bIsReleasing = false;
867 
868     if (!m_pRootBufferNode->hasAnything() &&
869         !m_pRootBufferNode->hasChildren() &&
870         m_xSAXEventKeeperStatusChangeListener.is())
871     {
872         m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
873     }
874 }
875 
markElementMarkBuffer(sal_Int32 nId)876 void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
877 /****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
878  *
879  *   NAME
880  *  markElementMarkBuffer -- marks an ElementMark to be released
881  *
882  *   SYNOPSIS
883  *  markElementMarkBuffer( nId );
884  *
885  *   FUNCTION
886  *  puts the ElementMark with the particular Id into the releasing list,
887  *  checks whether the releasing process is runing, if not then launch
888  *  this process.
889  *
890  *   INPUTS
891  *  nId - the Id of the ElementMark which will be released
892  *
893  *   RESULT
894  *  empty
895  *
896  *   HISTORY
897  *  05.01.2004 -    implemented
898  *
899  *   AUTHOR
900  *  Michael Mi
901  *  Email: michael.mi@sun.com
902  ******************************************************************************/
903 {
904     m_vReleasedElementMarkBuffers.push_back( nId );
905     if ( !m_bIsReleasing )
906     {
907         releaseElementMarkBuffer();
908     }
909 }
910 
createElementCollector(sal_Int32 nSecurityId,cssxc::sax::ElementMarkPriority nPriority,bool bModifyElement,const cssu::Reference<cssxc::sax::XReferenceResolvedListener> & xReferenceResolvedListener)911 sal_Int32 SAXEventKeeperImpl::createElementCollector(
912     sal_Int32 nSecurityId,
913     cssxc::sax::ElementMarkPriority nPriority,
914     bool bModifyElement,
915     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
916 /****** SAXEventKeeperImpl/createElementCollector ****************************
917  *
918  *   NAME
919  *  createElementCollector -- creates a new ElementCollector on the
920  *  incoming element.
921  *
922  *   SYNOPSIS
923  *  nId = createElementCollector( nSecurityId, nPriority,
924  *                               bModifyElement,
925  *                               xReferenceResolvedListener );
926  *
927  *   FUNCTION
928  *  allocs a new Id, then create an ElementCollector with this Id value.
929  *  Add the new created ElementCollector to the new ElementCollecotor list.
930  *
931  *   INPUTS
932  *  nSecurityId -   the security Id of the new ElementCollector
933  *  nPriority -     the prirority of the new ElementCollector
934  *  bModifyElement -whether this BufferNode will modify the content of
935  *                  the corresponding element it works on
936  *  xReferenceResolvedListener - the listener for the new ElementCollector.
937  *
938  *   RESULT
939  *  nId - the Id of the new ElementCollector
940  *
941  *   HISTORY
942  *  05.01.2004 -    implemented
943  *
944  *   AUTHOR
945  *  Michael Mi
946  *  Email: michael.mi@sun.com
947  ******************************************************************************/
948 {
949     sal_Int32 nId = m_nNextElementMarkId;
950     m_nNextElementMarkId ++;
951 
952     ElementCollector* pElementCollector
953         = new ElementCollector(
954             nSecurityId,
955             nId,
956             nPriority,
957             bModifyElement,
958             xReferenceResolvedListener);
959 
960     m_vElementMarkBuffers.push_back( pElementCollector );
961 
962         /*
963          * All the new EC to initial EC array.
964          */
965     m_vNewElementCollectors.push_back( pElementCollector );
966 
967     return nId;
968 }
969 
970 
createBlocker(sal_Int32 nSecurityId)971 sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
972 /****** SAXEventKeeperImpl/createBlocker *************************************
973  *
974  *   NAME
975  *  createBlocker -- creates a new Blocker on the incoming element.
976  *
977  *   SYNOPSIS
978  *  nId = createBlocker( nSecurityId );
979  *
980  *   FUNCTION
981  *  see NAME.
982  *
983  *   INPUTS
984  *  nSecurityId -   the security Id of the new Blocker
985  *
986  *   RESULT
987  *  nId - the Id of the new Blocker
988  *
989  *   HISTORY
990  *  05.01.2004 -    implemented
991  *
992  *   AUTHOR
993  *  Michael Mi
994  *  Email: michael.mi@sun.com
995  ******************************************************************************/
996 {
997     sal_Int32 nId = m_nNextElementMarkId;
998     m_nNextElementMarkId ++;
999 
1000     OSL_ASSERT(m_pNewBlocker == NULL);
1001 
1002     m_pNewBlocker = new ElementMark(nSecurityId, nId);
1003     m_vElementMarkBuffers.push_back( m_pNewBlocker );
1004 
1005     return nId;
1006 }
1007 
1008 /* XSAXEventKeeper */
addElementCollector()1009 sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector(  )
1010     throw (cssu::RuntimeException)
1011 {
1012     return createElementCollector(
1013         cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1014         cssxc::sax::ElementMarkPriority_AFTERMODIFY,
1015         false,
1016         NULL);
1017 }
1018 
removeElementCollector(sal_Int32 id)1019 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
1020     throw (cssu::RuntimeException)
1021 {
1022     markElementMarkBuffer(id);
1023 }
1024 
addBlocker()1025 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker(  )
1026     throw (cssu::RuntimeException)
1027 {
1028     return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
1029 }
1030 
removeBlocker(sal_Int32 id)1031 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
1032     throw (cssu::RuntimeException)
1033 {
1034     markElementMarkBuffer(id);
1035 }
1036 
isBlocking()1037 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking(  )
1038     throw (cssu::RuntimeException)
1039 {
1040     return (m_pCurrentBlockingBufferNode != NULL);
1041 }
1042 
1043 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
getElement(sal_Int32 id)1044     SAXEventKeeperImpl::getElement( sal_Int32 id )
1045     throw (cssu::RuntimeException)
1046 {
1047     cssu::Reference< cssxw::XXMLElementWrapper > rc;
1048 
1049     ElementMark* pElementMark = findElementMarkBuffer(id);
1050     if (pElementMark != NULL)
1051     {
1052         rc = pElementMark->getBufferNode()->getXMLElement();
1053     }
1054 
1055     return rc;
1056 }
1057 
setElement(sal_Int32 id,const cssu::Reference<cssxw::XXMLElementWrapper> & aElement)1058 void SAL_CALL SAXEventKeeperImpl::setElement(
1059     sal_Int32 id,
1060     const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1061     throw (cssu::RuntimeException)
1062 {
1063     if (aElement.is())
1064     {
1065         m_xXMLDocument->rebuildIDLink(aElement);
1066 
1067         ElementMark* pElementMark = findElementMarkBuffer(id);
1068 
1069         if (pElementMark != NULL)
1070         {
1071             BufferNode* pBufferNode = pElementMark->getBufferNode();
1072             if (pBufferNode != NULL)
1073             {
1074                     bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1075                 pBufferNode->setXMLElement(aElement);
1076 
1077                 if (bIsCurrent)
1078                 {
1079                     m_xXMLDocument->setCurrentElement(aElement);
1080                 }
1081             }
1082         }
1083     }
1084     else
1085     {
1086         removeElementCollector( id );
1087     }
1088 }
1089 
setNextHandler(const cssu::Reference<cssxs::XDocumentHandler> & xNewHandler)1090 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1091     const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1092     throw (cssu::RuntimeException)
1093 {
1094     cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1095 
1096     m_xNextHandler = xNewHandler;
1097     return xOldHandler;
1098 }
1099 
printBufferNodeTree()1100 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1101     throw (cssu::RuntimeException)
1102 {
1103     rtl::OUString rc;
1104 
1105     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
1106     rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
1107     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
1108     rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1109     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
1110     rc += printBufferNode(m_pRootBufferNode, 0);
1111 
1112     return rc;
1113 }
1114 
getCurrentBlockingNode()1115 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1116     throw (cssu::RuntimeException)
1117 {
1118     cssu::Reference< cssxw::XXMLElementWrapper > rc;
1119 
1120     if (m_pCurrentBlockingBufferNode != NULL)
1121     {
1122         rc = m_pCurrentBlockingBufferNode->getXMLElement();
1123     }
1124 
1125     return rc;
1126 }
1127 
1128 /* XSecuritySAXEventKeeper */
addSecurityElementCollector(cssxc::sax::ElementMarkPriority priority,sal_Bool modifyElement)1129 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1130     cssxc::sax::ElementMarkPriority priority,
1131     sal_Bool modifyElement )
1132     throw (cssu::RuntimeException)
1133 {
1134     return createElementCollector(
1135         cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1136         priority,
1137         modifyElement,
1138         NULL);
1139 }
1140 
cloneElementCollector(sal_Int32 referenceId,cssxc::sax::ElementMarkPriority priority)1141 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1142     sal_Int32 referenceId,
1143     cssxc::sax::ElementMarkPriority priority )
1144     throw (cssu::RuntimeException)
1145 {
1146     sal_Int32 nId = -1;
1147 
1148     ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1149     if (pElementCollector != NULL)
1150     {
1151         nId = m_nNextElementMarkId;
1152         m_nNextElementMarkId ++;
1153 
1154         ElementCollector* pClonedOne
1155             = pElementCollector->clone(nId, priority);
1156 
1157             /*
1158              * add this EC into the security data buffer array.
1159              */
1160         m_vElementMarkBuffers.push_back(pClonedOne);
1161 
1162             /*
1163              * If the reference EC is still in initial EC array, add
1164              * this cloned one into the initial EC array too.
1165              */
1166             if (pElementCollector->getBufferNode() == NULL)
1167         {
1168             m_vNewElementCollectors.push_back(pClonedOne);
1169         }
1170     }
1171 
1172     return nId;
1173 }
1174 
setSecurityId(sal_Int32 id,sal_Int32 securityId)1175 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1176     throw (cssu::RuntimeException)
1177 {
1178     ElementMark* pElementMark = findElementMarkBuffer(id);
1179     if (pElementMark != NULL)
1180     {
1181         pElementMark->setSecurityId(securityId);
1182     }
1183 }
1184 
1185 
1186 /* XReferenceResolvedBroadcaster */
addReferenceResolvedListener(sal_Int32 referenceId,const cssu::Reference<cssxc::sax::XReferenceResolvedListener> & listener)1187 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1188     sal_Int32 referenceId,
1189     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1190     throw (cssu::RuntimeException)
1191 {
1192     ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1193     if (pElementCollector != NULL)
1194     {
1195         pElementCollector->setReferenceResolvedListener(listener);
1196     }
1197 }
1198 
removeReferenceResolvedListener(sal_Int32,const cssu::Reference<cssxc::sax::XReferenceResolvedListener> &)1199 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1200     sal_Int32 /*referenceId*/,
1201     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1202     throw (cssu::RuntimeException)
1203 {
1204 }
1205 
1206 /* XSAXEventKeeperStatusChangeBroadcaster */
addSAXEventKeeperStatusChangeListener(const cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeListener> & listener)1207 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1208     const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1209     throw (cssu::RuntimeException)
1210 {
1211     m_xSAXEventKeeperStatusChangeListener = listener;
1212 }
1213 
removeSAXEventKeeperStatusChangeListener(const cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeListener> &)1214 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1215     const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1216     throw (cssu::RuntimeException)
1217 {
1218 }
1219 
1220 /* XDocumentHandler */
startDocument()1221 void SAL_CALL SAXEventKeeperImpl::startDocument(  )
1222     throw (cssxs::SAXException, cssu::RuntimeException)
1223 {
1224     if ( m_xNextHandler.is())
1225     {
1226         m_xNextHandler->startDocument();
1227     }
1228 }
1229 
endDocument()1230 void SAL_CALL SAXEventKeeperImpl::endDocument(  )
1231     throw (cssxs::SAXException, cssu::RuntimeException)
1232 {
1233     if ( m_xNextHandler.is())
1234     {
1235         m_xNextHandler->endDocument();
1236     }
1237 }
1238 
startElement(const rtl::OUString & aName,const cssu::Reference<cssxs::XAttributeList> & xAttribs)1239 void SAL_CALL SAXEventKeeperImpl::startElement(
1240     const rtl::OUString& aName,
1241     const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1242     throw (cssxs::SAXException, cssu::RuntimeException)
1243 {
1244         /*
1245          * If there is a following handler and no blocking now, then
1246          * forward this event
1247          */
1248     if ((m_pCurrentBlockingBufferNode == NULL) &&
1249         (m_xNextHandler.is()) &&
1250         (!m_bIsForwarding) &&
1251         (m_pNewBlocker == NULL))
1252     {
1253         m_xNextHandler->startElement(aName, xAttribs);
1254     }
1255 
1256         /*
1257          * If not forwarding, buffer this startElement.
1258          */
1259         if (!m_bIsForwarding)
1260         {
1261     #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1262         m_xDocumentHandler->startElement(aName, xAttribs);
1263     #else
1264         sal_Int32 nLength = xAttribs->getLength();
1265         cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1266 
1267         for ( int i = 0; i<nLength; ++i )
1268         {
1269             aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1270             aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1271         }
1272 
1273         m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
1274     #endif
1275 
1276     }
1277 
1278     BufferNode* pBufferNode = addNewElementMarkBuffers();
1279         if (pBufferNode != NULL)
1280         {
1281         setCurrentBufferNode(pBufferNode);
1282     }
1283 }
1284 
endElement(const rtl::OUString & aName)1285 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
1286     throw (cssxs::SAXException, cssu::RuntimeException)
1287 {
1288         sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1289 
1290         /*
1291          * If there is a following handler and no blocking now, then
1292          * forward this event
1293          */
1294     if ((m_pCurrentBlockingBufferNode == NULL) &&
1295         (m_xNextHandler.is()) &&
1296         (!m_bIsForwarding))
1297     {
1298         m_xNextHandler->endElement(aName);
1299     }
1300 
1301     if ((m_pCurrentBlockingBufferNode != NULL) ||
1302         (m_pCurrentBufferNode != m_pRootBufferNode) ||
1303         (!m_xXMLDocument->isCurrentElementEmpty()))
1304     {
1305             if (!m_bIsForwarding)
1306             {
1307         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1308             m_xDocumentHandler->endElement(aName);
1309         #else
1310             m_xCompressedDocumentHandler->_endElement(aName);
1311         #endif
1312         }
1313 
1314         /*
1315         * If the current buffer node has not notified yet, and
1316         * the current buffer node is waiting for the current element,
1317         * then let it notify.
1318         */
1319         if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1320         {
1321             BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1322             m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
1323 
1324             pOldCurrentBufferNode->setReceivedAll();
1325 
1326             if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1327                 m_xSAXEventKeeperStatusChangeListener.is())
1328             {
1329                 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1330             }
1331         }
1332     }
1333     else
1334     {
1335         if (!m_bIsForwarding)
1336         {
1337             m_xXMLDocument->removeCurrentElement();
1338         }
1339     }
1340 }
1341 
characters(const rtl::OUString & aChars)1342 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
1343     throw (cssxs::SAXException, cssu::RuntimeException)
1344 {
1345     if (!m_bIsForwarding)
1346     {
1347         if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1348         {
1349             m_xNextHandler->characters(aChars);
1350         }
1351 
1352         if ((m_pCurrentBlockingBufferNode != NULL) ||
1353             (m_pCurrentBufferNode != m_pRootBufferNode))
1354         {
1355         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1356                 m_xDocumentHandler->characters(aChars);
1357         #else
1358             m_xCompressedDocumentHandler->_characters(aChars);
1359         #endif
1360             }
1361         }
1362 }
1363 
ignorableWhitespace(const rtl::OUString & aWhitespaces)1364 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1365     throw (cssxs::SAXException, cssu::RuntimeException)
1366 {
1367     characters( aWhitespaces );
1368 }
1369 
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1370 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1371     const rtl::OUString& aTarget, const rtl::OUString& aData )
1372     throw (cssxs::SAXException, cssu::RuntimeException)
1373 {
1374     if (!m_bIsForwarding)
1375     {
1376         if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1377         {
1378             m_xNextHandler->processingInstruction(aTarget, aData);
1379         }
1380 
1381         if ((m_pCurrentBlockingBufferNode != NULL) ||
1382             (m_pCurrentBufferNode != m_pRootBufferNode))
1383         {
1384         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1385             m_xDocumentHandler->processingInstruction(aTarget, aData);
1386         #else
1387             m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
1388         #endif
1389             }
1390         }
1391 }
1392 
setDocumentLocator(const cssu::Reference<cssxs::XLocator> &)1393 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1394     throw (cssxs::SAXException, cssu::RuntimeException)
1395 {
1396 }
1397 
1398 /* XInitialization */
initialize(const cssu::Sequence<cssu::Any> & aArguments)1399 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1400     throw (cssu::Exception, cssu::RuntimeException)
1401 {
1402     OSL_ASSERT(aArguments.getLength() == 1);
1403 
1404     aArguments[0] >>= m_xXMLDocument;
1405     m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1406         m_xXMLDocument, cssu::UNO_QUERY );
1407     m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1408         m_xXMLDocument, cssu::UNO_QUERY );
1409 
1410     m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1411     m_pCurrentBufferNode = m_pRootBufferNode;
1412 }
1413 
SAXEventKeeperImpl_getImplementationName()1414 rtl::OUString SAXEventKeeperImpl_getImplementationName ()
1415     throw (cssu::RuntimeException)
1416 {
1417     return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1418 }
1419 
SAXEventKeeperImpl_supportsService(const rtl::OUString & ServiceName)1420 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
1421     throw (cssu::RuntimeException)
1422 {
1423     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1424 }
1425 
SAXEventKeeperImpl_getSupportedServiceNames()1426 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames(  )
1427     throw (cssu::RuntimeException)
1428 {
1429     cssu::Sequence < rtl::OUString > aRet(1);
1430     rtl::OUString* pArray = aRet.getArray();
1431     pArray[0] =  rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1432     return aRet;
1433 }
1434 #undef SERVICE_NAME
1435 
SAXEventKeeperImpl_createInstance(const cssu::Reference<cssl::XMultiServiceFactory> &)1436 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1437     const cssu::Reference< cssl::XMultiServiceFactory > &)
1438     throw( cssu::Exception )
1439 {
1440     return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1441 }
1442 
1443 /* XServiceInfo */
getImplementationName()1444 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName(  )
1445     throw (cssu::RuntimeException)
1446 {
1447     return SAXEventKeeperImpl_getImplementationName();
1448 }
supportsService(const rtl::OUString & rServiceName)1449 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
1450     throw (cssu::RuntimeException)
1451 {
1452     return SAXEventKeeperImpl_supportsService( rServiceName );
1453 }
getSupportedServiceNames()1454 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames(  )
1455     throw (cssu::RuntimeException)
1456 {
1457     return SAXEventKeeperImpl_getSupportedServiceNames();
1458 }
1459 
1460