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