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