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