xref: /trunk/main/xmlsecurity/source/framework/saxeventkeeperimpl.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 blocker 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 running, 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 {
1011     return createElementCollector(
1012         cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1013         cssxc::sax::ElementMarkPriority_AFTERMODIFY,
1014         false,
1015         NULL);
1016 }
1017 
removeElementCollector(sal_Int32 id)1018 void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
1019 {
1020     markElementMarkBuffer(id);
1021 }
1022 
addBlocker()1023 sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker(  )
1024 {
1025     return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
1026 }
1027 
removeBlocker(sal_Int32 id)1028 void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
1029 {
1030     markElementMarkBuffer(id);
1031 }
1032 
isBlocking()1033 sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking(  )
1034 {
1035     return (m_pCurrentBlockingBufferNode != NULL);
1036 }
1037 
1038 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
getElement(sal_Int32 id)1039     SAXEventKeeperImpl::getElement( sal_Int32 id )
1040 {
1041     cssu::Reference< cssxw::XXMLElementWrapper > rc;
1042 
1043     ElementMark* pElementMark = findElementMarkBuffer(id);
1044     if (pElementMark != NULL)
1045     {
1046         rc = pElementMark->getBufferNode()->getXMLElement();
1047     }
1048 
1049     return rc;
1050 }
1051 
setElement(sal_Int32 id,const cssu::Reference<cssxw::XXMLElementWrapper> & aElement)1052 void SAL_CALL SAXEventKeeperImpl::setElement(
1053     sal_Int32 id,
1054     const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
1055 {
1056     if (aElement.is())
1057     {
1058         m_xXMLDocument->rebuildIDLink(aElement);
1059 
1060         ElementMark* pElementMark = findElementMarkBuffer(id);
1061 
1062         if (pElementMark != NULL)
1063         {
1064             BufferNode* pBufferNode = pElementMark->getBufferNode();
1065             if (pBufferNode != NULL)
1066             {
1067                     bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
1068                 pBufferNode->setXMLElement(aElement);
1069 
1070                 if (bIsCurrent)
1071                 {
1072                     m_xXMLDocument->setCurrentElement(aElement);
1073                 }
1074             }
1075         }
1076     }
1077     else
1078     {
1079         removeElementCollector( id );
1080     }
1081 }
1082 
setNextHandler(const cssu::Reference<cssxs::XDocumentHandler> & xNewHandler)1083 cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
1084     const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
1085 {
1086     cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
1087 
1088     m_xNextHandler = xNewHandler;
1089     return xOldHandler;
1090 }
1091 
printBufferNodeTree()1092 rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
1093 {
1094     rtl::OUString rc;
1095 
1096     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
1097     rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
1098     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
1099     rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
1100     rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
1101     rc += printBufferNode(m_pRootBufferNode, 0);
1102 
1103     return rc;
1104 }
1105 
getCurrentBlockingNode()1106 cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
1107 {
1108     cssu::Reference< cssxw::XXMLElementWrapper > rc;
1109 
1110     if (m_pCurrentBlockingBufferNode != NULL)
1111     {
1112         rc = m_pCurrentBlockingBufferNode->getXMLElement();
1113     }
1114 
1115     return rc;
1116 }
1117 
1118 /* XSecuritySAXEventKeeper */
addSecurityElementCollector(cssxc::sax::ElementMarkPriority priority,sal_Bool modifyElement)1119 sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
1120     cssxc::sax::ElementMarkPriority priority,
1121     sal_Bool modifyElement )
1122 {
1123     return createElementCollector(
1124         cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
1125         priority,
1126         modifyElement,
1127         NULL);
1128 }
1129 
cloneElementCollector(sal_Int32 referenceId,cssxc::sax::ElementMarkPriority priority)1130 sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
1131     sal_Int32 referenceId,
1132     cssxc::sax::ElementMarkPriority priority )
1133 {
1134     sal_Int32 nId = -1;
1135 
1136     ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1137     if (pElementCollector != NULL)
1138     {
1139         nId = m_nNextElementMarkId;
1140         m_nNextElementMarkId ++;
1141 
1142         ElementCollector* pClonedOne
1143             = pElementCollector->clone(nId, priority);
1144 
1145             /*
1146              * add this EC into the security data buffer array.
1147              */
1148         m_vElementMarkBuffers.push_back(pClonedOne);
1149 
1150             /*
1151              * If the reference EC is still in initial EC array, add
1152              * this cloned one into the initial EC array too.
1153              */
1154             if (pElementCollector->getBufferNode() == NULL)
1155         {
1156             m_vNewElementCollectors.push_back(pClonedOne);
1157         }
1158     }
1159 
1160     return nId;
1161 }
1162 
setSecurityId(sal_Int32 id,sal_Int32 securityId)1163 void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
1164 {
1165     ElementMark* pElementMark = findElementMarkBuffer(id);
1166     if (pElementMark != NULL)
1167     {
1168         pElementMark->setSecurityId(securityId);
1169     }
1170 }
1171 
1172 
1173 /* XReferenceResolvedBroadcaster */
addReferenceResolvedListener(sal_Int32 referenceId,const cssu::Reference<cssxc::sax::XReferenceResolvedListener> & listener)1174 void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
1175     sal_Int32 referenceId,
1176     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
1177 {
1178     ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
1179     if (pElementCollector != NULL)
1180     {
1181         pElementCollector->setReferenceResolvedListener(listener);
1182     }
1183 }
1184 
removeReferenceResolvedListener(sal_Int32,const cssu::Reference<cssxc::sax::XReferenceResolvedListener> &)1185 void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
1186     sal_Int32 /*referenceId*/,
1187     const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
1188 {
1189 }
1190 
1191 /* XSAXEventKeeperStatusChangeBroadcaster */
addSAXEventKeeperStatusChangeListener(const cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeListener> & listener)1192 void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
1193     const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
1194 {
1195     m_xSAXEventKeeperStatusChangeListener = listener;
1196 }
1197 
removeSAXEventKeeperStatusChangeListener(const cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeListener> &)1198 void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
1199     const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
1200 {
1201 }
1202 
1203 /* XDocumentHandler */
startDocument()1204 void SAL_CALL SAXEventKeeperImpl::startDocument(  )
1205 {
1206     if ( m_xNextHandler.is())
1207     {
1208         m_xNextHandler->startDocument();
1209     }
1210 }
1211 
endDocument()1212 void SAL_CALL SAXEventKeeperImpl::endDocument(  )
1213 {
1214     if ( m_xNextHandler.is())
1215     {
1216         m_xNextHandler->endDocument();
1217     }
1218 }
1219 
startElement(const rtl::OUString & aName,const cssu::Reference<cssxs::XAttributeList> & xAttribs)1220 void SAL_CALL SAXEventKeeperImpl::startElement(
1221     const rtl::OUString& aName,
1222     const cssu::Reference< cssxs::XAttributeList >& xAttribs )
1223 {
1224         /*
1225          * If there is a following handler and no blocking now, then
1226          * forward this event
1227          */
1228     if ((m_pCurrentBlockingBufferNode == NULL) &&
1229         (m_xNextHandler.is()) &&
1230         (!m_bIsForwarding) &&
1231         (m_pNewBlocker == NULL))
1232     {
1233         m_xNextHandler->startElement(aName, xAttribs);
1234     }
1235 
1236         /*
1237          * If not forwarding, buffer this startElement.
1238          */
1239         if (!m_bIsForwarding)
1240         {
1241     #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1242         m_xDocumentHandler->startElement(aName, xAttribs);
1243     #else
1244         sal_Int32 nLength = xAttribs->getLength();
1245         cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
1246 
1247         for ( int i = 0; i<nLength; ++i )
1248         {
1249             aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
1250             aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
1251         }
1252 
1253         m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
1254     #endif
1255 
1256     }
1257 
1258     BufferNode* pBufferNode = addNewElementMarkBuffers();
1259         if (pBufferNode != NULL)
1260         {
1261         setCurrentBufferNode(pBufferNode);
1262     }
1263 }
1264 
endElement(const rtl::OUString & aName)1265 void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
1266 {
1267         sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
1268 
1269         /*
1270          * If there is a following handler and no blocking now, then
1271          * forward this event
1272          */
1273     if ((m_pCurrentBlockingBufferNode == NULL) &&
1274         (m_xNextHandler.is()) &&
1275         (!m_bIsForwarding))
1276     {
1277         m_xNextHandler->endElement(aName);
1278     }
1279 
1280     if ((m_pCurrentBlockingBufferNode != NULL) ||
1281         (m_pCurrentBufferNode != m_pRootBufferNode) ||
1282         (!m_xXMLDocument->isCurrentElementEmpty()))
1283     {
1284             if (!m_bIsForwarding)
1285             {
1286         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1287             m_xDocumentHandler->endElement(aName);
1288         #else
1289             m_xCompressedDocumentHandler->_endElement(aName);
1290         #endif
1291         }
1292 
1293         /*
1294         * If the current buffer node has not notified yet, and
1295         * the current buffer node is waiting for the current element,
1296         * then let it notify.
1297         */
1298         if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
1299         {
1300             BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
1301             m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
1302 
1303             pOldCurrentBufferNode->setReceivedAll();
1304 
1305             if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
1306                 m_xSAXEventKeeperStatusChangeListener.is())
1307             {
1308                 m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
1309             }
1310         }
1311     }
1312     else
1313     {
1314         if (!m_bIsForwarding)
1315         {
1316             m_xXMLDocument->removeCurrentElement();
1317         }
1318     }
1319 }
1320 
characters(const rtl::OUString & aChars)1321 void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
1322 {
1323     if (!m_bIsForwarding)
1324     {
1325         if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1326         {
1327             m_xNextHandler->characters(aChars);
1328         }
1329 
1330         if ((m_pCurrentBlockingBufferNode != NULL) ||
1331             (m_pCurrentBufferNode != m_pRootBufferNode))
1332         {
1333         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1334                 m_xDocumentHandler->characters(aChars);
1335         #else
1336             m_xCompressedDocumentHandler->_characters(aChars);
1337         #endif
1338             }
1339         }
1340 }
1341 
ignorableWhitespace(const rtl::OUString & aWhitespaces)1342 void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
1343 {
1344     characters( aWhitespaces );
1345 }
1346 
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)1347 void SAL_CALL SAXEventKeeperImpl::processingInstruction(
1348     const rtl::OUString& aTarget, const rtl::OUString& aData )
1349 {
1350     if (!m_bIsForwarding)
1351     {
1352         if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
1353         {
1354             m_xNextHandler->processingInstruction(aTarget, aData);
1355         }
1356 
1357         if ((m_pCurrentBlockingBufferNode != NULL) ||
1358             (m_pCurrentBufferNode != m_pRootBufferNode))
1359         {
1360         #ifndef _USECOMPRESSEDDOCUMENTHANDLER
1361             m_xDocumentHandler->processingInstruction(aTarget, aData);
1362         #else
1363             m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
1364         #endif
1365             }
1366         }
1367 }
1368 
setDocumentLocator(const cssu::Reference<cssxs::XLocator> &)1369 void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
1370 {
1371 }
1372 
1373 /* XInitialization */
initialize(const cssu::Sequence<cssu::Any> & aArguments)1374 void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
1375 {
1376     OSL_ASSERT(aArguments.getLength() == 1);
1377 
1378     aArguments[0] >>= m_xXMLDocument;
1379     m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
1380         m_xXMLDocument, cssu::UNO_QUERY );
1381     m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
1382         m_xXMLDocument, cssu::UNO_QUERY );
1383 
1384     m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
1385     m_pCurrentBufferNode = m_pRootBufferNode;
1386 }
1387 
SAXEventKeeperImpl_getImplementationName()1388 rtl::OUString SAXEventKeeperImpl_getImplementationName ()
1389 {
1390     return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
1391 }
1392 
SAXEventKeeperImpl_supportsService(const rtl::OUString & ServiceName)1393 sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
1394 {
1395     return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
1396 }
1397 
SAXEventKeeperImpl_getSupportedServiceNames()1398 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames(  )
1399 {
1400     cssu::Sequence < rtl::OUString > aRet(1);
1401     rtl::OUString* pArray = aRet.getArray();
1402     pArray[0] =  rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
1403     return aRet;
1404 }
1405 #undef SERVICE_NAME
1406 
SAXEventKeeperImpl_createInstance(const cssu::Reference<cssl::XMultiServiceFactory> &)1407 cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
1408     const cssu::Reference< cssl::XMultiServiceFactory > &)
1409 {
1410     return (cppu::OWeakObject*) new SAXEventKeeperImpl();
1411 }
1412 
1413 /* XServiceInfo */
getImplementationName()1414 rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName(  )
1415 {
1416     return SAXEventKeeperImpl_getImplementationName();
1417 }
supportsService(const rtl::OUString & rServiceName)1418 sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
1419 {
1420     return SAXEventKeeperImpl_supportsService( rServiceName );
1421 }
getSupportedServiceNames()1422 cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames(  )
1423 {
1424     return SAXEventKeeperImpl_getSupportedServiceNames();
1425 }
1426