summaryrefslogtreecommitdiff
path: root/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
diff options
context:
space:
mode:
authorMalte Timmermann <mt@openoffice.org>2004-07-12 12:15:31 +0000
committerMalte Timmermann <mt@openoffice.org>2004-07-12 12:15:31 +0000
commitdacd1d7e88dc6d9b44c05685e0a2b256606b39c9 (patch)
treed080282db103de69bcfa3d6812677d67751f0f7d /xmlsecurity/source/framework/saxeventkeeperimpl.cxx
parent22b822e1e0528b1980830135358d609407982f63 (diff)
libxmlsec
Diffstat (limited to 'xmlsecurity/source/framework/saxeventkeeperimpl.cxx')
-rw-r--r--xmlsecurity/source/framework/saxeventkeeperimpl.cxx1503
1 files changed, 1503 insertions, 0 deletions
diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
new file mode 100644
index 000000000..ed3a5543c
--- /dev/null
+++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
@@ -0,0 +1,1503 @@
+/*************************************************************************
+ *
+ * $RCSfile: saxeventkeeperimpl.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: mt $ $Date: 2004-07-12 13:15:22 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include "saxeventkeeperimpl.hxx"
+
+#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#endif
+#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#endif
+#ifndef _COM_SUN_STAR_XML_CRYPTO_SAX_CONSTOFSECURITYID_HPP_
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#endif
+
+namespace cssu = com::sun::star::uno;
+namespace cssl = com::sun::star::lang;
+namespace cssxc = com::sun::star::xml::crypto;
+namespace cssxcsax = com::sun::star::xml::csax;
+namespace cssxw = com::sun::star::xml::wrapper;
+namespace cssxs = com::sun::star::xml::sax;
+
+#define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
+#define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"
+
+#define _USECOMPRESSEDDOCUMENTHANDLER
+
+SAXEventKeeperImpl::SAXEventKeeperImpl( )
+ :m_nNextElementMarkId(1),
+ m_pNewBlocker(NULL),
+ m_pCurrentBlockingBufferNode(NULL),
+ m_pRootBufferNode(NULL),
+ m_pCurrentBufferNode(NULL),
+ m_bIsForwarding(false),
+ m_bIsReleasing(false)
+{
+ m_vElementMarkBuffers.reserve(2);
+ m_vNewElementCollectors.reserve(2);
+ m_vReleasedElementMarkBuffers.reserve(2);
+}
+
+SAXEventKeeperImpl::~SAXEventKeeperImpl()
+{
+ /*
+ * delete the BufferNode tree
+ */
+ if (m_pRootBufferNode != NULL)
+ {
+ m_pRootBufferNode->freeAllChildren();
+ delete m_pRootBufferNode;
+ }
+
+ m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;
+
+ /*
+ * delete all unfreed ElementMarks
+ */
+ m_vNewElementCollectors.clear();
+ m_pNewBlocker = NULL;
+
+ std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
+ for( ; ii != m_vElementMarkBuffers.end(); ++ii )
+ {
+ delete (*ii);
+ }
+ m_vElementMarkBuffers.clear();
+}
+
+void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
+/****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
+ *
+ * NAME
+ * setCurrentBufferNode -- set a new active BufferNode.
+ *
+ * SYNOPSIS
+ * setCurrentBufferNode( pBufferNode );
+ *
+ * FUNCTION
+ * connects this BufferNode into the BufferNode tree as a child of the
+ * current active BufferNode. Then makes this BufferNode as the current
+ * active BufferNode.
+ * If the previous active BufferNode points to the root
+ * BufferNode, which means that no buffering operation was proceeding,
+ * then notifies the status change listener that buffering operation
+ * will begin at once.
+ *
+ * INPUTS
+ * pBufferNode - a BufferNode which will be the new active BufferNode
+ *
+ * RESULT
+ * empty
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ if (pBufferNode != m_pCurrentBufferNode)
+ {
+ if ( m_pCurrentBufferNode == m_pRootBufferNode &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
+ }
+
+ if (pBufferNode->getParent() == NULL)
+ {
+ m_pCurrentBufferNode->addChild(pBufferNode);
+ pBufferNode->setParent(m_pCurrentBufferNode);
+ }
+
+ m_pCurrentBufferNode = pBufferNode;
+ }
+}
+
+BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
+/****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
+ *
+ * NAME
+ * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
+ *
+ * SYNOPSIS
+ * pBufferNode = addNewElementMarkBuffers( );
+ *
+ * FUNCTION
+ * if there are new ElementCollector or new Blocker to be added, then
+ * connect all of them with the current BufferNode. In case of the
+ * current BufferNode doesn't exist, creates one.
+ * Clears up the new ElementCollector list and the new Blocker pointer.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * pBufferNode - the BufferNode that has been connected with both new
+ * ElementCollectors and new Blocker.
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ BufferNode* pBufferNode = NULL;
+
+ if ( (m_vNewElementCollectors.size()>0) ||
+ (m_pNewBlocker != NULL))
+ {
+ /*
+ * When the current BufferNode is right pointing to the current
+ * working element in the XMLDocumentWrapper component, then
+ * no new BufferNode is needed to create.
+ * This situation can only happen in the "Forwarding" mode.
+ */
+ if ( (m_pCurrentBufferNode != NULL) &&
+ (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
+ {
+ pBufferNode = m_pCurrentBufferNode;
+ }
+ else
+ {
+ pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
+ }
+
+ if (m_pNewBlocker != NULL)
+ {
+ pBufferNode->setBlocker(m_pNewBlocker);
+
+ /*
+ * If no blocking before, then notify the status change listener that
+ * the SAXEventKeeper has entered "blocking" status, during which, no
+ * SAX events will be forwarded to the next document handler.
+ */
+ if (m_pCurrentBlockingBufferNode == NULL)
+ {
+ m_pCurrentBlockingBufferNode = pBufferNode;
+
+ if (m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
+ }
+ }
+
+ m_pNewBlocker = NULL;
+ }
+
+ if (m_vNewElementCollectors.size()>0)
+ {
+ std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();
+
+ for( ; ii != m_vNewElementCollectors.end(); ++ii )
+ {
+ pBufferNode->addElementCollector(*ii);
+ }
+
+ m_vNewElementCollectors.clear();
+ }
+ }
+
+ return pBufferNode;
+}
+
+ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
+/****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
+ *
+ * NAME
+ * findElementMarkBuffer -- finds an ElementMark.
+ *
+ * SYNOPSIS
+ * pElementMark = findElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * searches an ElementMark with the particular Id in the ElementMark
+ * list.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark to be searched.
+ *
+ * RESULT
+ * pElementMark - the ElementMark with the particular Id, or NULL when
+ * no such Id exists.
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ ElementMark* pElementMark = NULL;
+
+ std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
+
+ for( ; ii != m_vElementMarkBuffers.end(); ++ii )
+ {
+ if ( nId == (*ii)->getBufferId())
+ {
+ pElementMark = (ElementMark*)*ii;
+ break;
+ }
+ }
+
+ return pElementMark;
+}
+
+void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
+/****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
+ *
+ * NAME
+ * removeElementMarkBuffer -- removes an ElementMark
+ *
+ * SYNOPSIS
+ * removeElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * removes an ElementMark with the particular Id in the ElementMark list.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark to be removed.
+ *
+ * RESULT
+ * empty
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();
+
+ for( ; ii != m_vElementMarkBuffers.end(); ++ii )
+ {
+ if ( nId == (*ii)->getBufferId())
+ {
+ /*
+ * checks whether this ElementMark still in the new ElementCollect array
+ */
+ std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
+ for( ; jj != m_vNewElementCollectors.end(); ++jj )
+ {
+ if ((*ii) == (*jj))
+ {
+ m_vNewElementCollectors.erase(jj);
+ break;
+ }
+ }
+
+ /*
+ * checks whether this ElementMark is the new Blocker
+ */
+ if ((*ii) == m_pNewBlocker)
+ {
+ m_pNewBlocker = NULL;
+ }
+
+ /*
+ * destory the ElementMark
+ */
+ delete (*ii);
+
+ m_vElementMarkBuffers.erase( ii );
+ break;
+ }
+ }
+}
+
+rtl::OUString SAXEventKeeperImpl::printBufferNode(
+ BufferNode* pBufferNode, sal_Int32 nIndent) const
+/****** SAXEventKeeperImpl/printBufferNode ***********************************
+ *
+ * NAME
+ * printBufferNode -- retrieves the information of a BufferNode and its
+ * branch.
+ *
+ * SYNOPSIS
+ * info = printBufferNode( pBufferNode, nIndent );
+ *
+ * FUNCTION
+ * all retrieved information includes:
+ * 1. whether it is the current BufferNode;
+ * 2. whether it is the current blocking BufferNode;
+ * 3. the name of the parent element;
+ * 4. the name of this element;
+ * 5. all ElementCollectors working on this BufferNode;
+ * 6. the Blocker working on this BufferNode;
+ * 7. all child BufferNodes' information.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode from where information will be retrieved.
+ * nIndent - how many space characters prefixed before the output
+ * message.
+ *
+ * RESULT
+ * info - the information string
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ rtl::OUString rc;
+
+ for ( int i=0; i<nIndent; ++i )
+ {
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
+ }
+
+ if (pBufferNode == m_pCurrentBufferNode)
+ {
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
+ }
+
+ if (pBufferNode == m_pCurrentBlockingBufferNode)
+ {
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
+ }
+
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
+ rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());
+
+ BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
+ if (pParent != NULL)
+ {
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
+ rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
+ }
+
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
+ rc += pBufferNode->printChildren();
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));
+
+ ElementMark * pBlocker = pBufferNode->getBlocker();
+ if (pBlocker != NULL)
+ {
+ rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
+ rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
+ }
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
+
+ std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
+ std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
+ for( ; jj != vChildren->end(); ++jj )
+ {
+ rc += printBufferNode((BufferNode *)*jj, nIndent+4);
+ }
+
+ delete vChildren;
+
+ return rc;
+}
+
+cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
+ SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
+/****** SAXEventKeeperImpl/collectChildWorkingElement ************************
+ *
+ * NAME
+ * collectChildWorkingElement -- collects a BufferNode's all child
+ * Elements.
+ *
+ * SYNOPSIS
+ * list = collectChildWorkingElement( pBufferNode );
+ *
+ * FUNCTION
+ * see NAME.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode whose child Elements will be collected.
+ *
+ * RESULT
+ * list - the child Elements list.
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
+
+ cssu::Sequence < cssu::Reference<
+ cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());
+
+ std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();
+
+ sal_Int32 nIndex = 0;
+ for( ; ii != vChildren->end(); ++ii )
+ {
+ aChildrenCollection[nIndex] = (*ii)->getXMLElement();
+ nIndex++;
+ }
+
+ delete vChildren;
+
+ return aChildrenCollection;
+}
+
+void SAXEventKeeperImpl::smashBufferNode(
+ BufferNode* pBufferNode, bool bClearRoot) const
+/****** SAXEventKeeperImpl/smashBufferNode ***********************************
+ *
+ * NAME
+ * smashBufferNode -- removes a BufferNode along with its working
+ * element.
+ *
+ * SYNOPSIS
+ * smashBufferNode( pBufferNode, bClearRoot );
+ *
+ * FUNCTION
+ * removes the BufferNode's working element from the DOM document, while
+ * reserves all ancestor paths for its child BufferNodes.
+ * when any of the BufferNode's ancestor element is useless, removes it
+ * too.
+ * removes the BufferNode from the BufferNode tree.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode to be removed
+ * bClearRoot - whether the root element also needs to be cleared up.
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * when removeing a Blocker's BufferNode, the bClearRoot flag should be
+ * true. Because a Blocker can buffer many SAX events which are not used
+ * by any other ElementCollector or Blocker.
+ * When the bClearRoot is set to true, the root BufferNode will be first
+ * cleared, with a stop flag seting at the next Blocking BufferNode. This
+ * operation can delete all useless bufferred SAX events which are only
+ * needed by the Blocker to be deleted.
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ if (!pBufferNode->hasAnything())
+ {
+ BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
+
+ /*
+ * delete the XML data
+ */
+ if (pParent == m_pRootBufferNode)
+ {
+ bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
+ bool bIsBlockInside = false;
+ bool bIsBlockingAfterward = false;
+
+ /*
+ * If this is a blocker, then remove any out-element data
+ * which caused by blocking. The removal process will stop
+ * at the next blokcer to avoid removing any useful data.
+ */
+ if (bClearRoot)
+ {
+ cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
+ aChildElements = collectChildWorkingElement(m_pRootBufferNode);
+
+ /*
+ * the clearUselessData only clearup the content in the
+ * node, not the node itself.
+ */
+ m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
+ aChildElements,
+ bIsNotBlocking?(NULL):
+ (m_pCurrentBlockingBufferNode->getXMLElement()));
+
+ /*
+ * remove the node if it is empty, then if its parent is also
+ * empty, remove it, then if the next parent is also empty,
+ * remove it,..., until parent become null.
+ */
+ m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
+ }
+
+ /*
+ * if blocking, check the relationship between this BufferNode and
+ * the current blocking BufferNode.
+ */
+ if ( !bIsNotBlocking )
+ {
+ /*
+ * the current blocking BufferNode is a descendant of this BufferNode.
+ */
+ bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
+
+ /*
+ * the current blocking BufferNode locates behind this BufferNode in tree
+ * order.
+ */
+ bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
+ }
+
+ /*
+ * this BufferNode's working element needs to be deleted only when
+ * 1. there is no blocking, or
+ * 2. the current blocking BufferNode is a descendant of this BufferNode,
+ * (then in the BufferNode's working element, the useless data before the blocking
+ * element should be deleted.) or
+ * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
+ * (then the useless data between the blocking element and the working element
+ * should be deleted.).
+ * Otherwise, this working element should not be deleted.
+ */
+ if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
+ {
+ cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
+ aChildElements = collectChildWorkingElement(pBufferNode);
+
+ /*
+ * the clearUselessData only clearup the content in the
+ * node, not the node itself.
+ */
+ m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
+ aChildElements,
+ bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
+ (NULL));
+
+ /*
+ * remove the node if it is empty, then if its parent is also
+ * empty, remove it, then if the next parent is also empty,
+ * remove it,..., until parent become null.
+ */
+ m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
+ }
+ }
+
+ sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
+
+ std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
+ pParent->removeChild(pBufferNode);
+ pBufferNode->setParent(NULL);
+
+ std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
+ for( ; ii != vChildren->end(); ++ii )
+ {
+ ((BufferNode *)(*ii))->setParent(pParent);
+ pParent->addChild(*ii, nIndex);
+ nIndex++;
+ }
+
+ delete vChildren;
+
+ /*
+ * delete the BufferNode
+ */
+ delete pBufferNode;
+ }
+}
+
+BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
+ BufferNode* pStartBufferNode) const
+/****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
+ *
+ * NAME
+ * findNextBlockingBufferNode -- finds the next blocking BufferNode
+ * behind the particular BufferNode.
+ *
+ * SYNOPSIS
+ * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
+ *
+ * FUNCTION
+ * see NAME.
+ *
+ * INPUTS
+ * pStartBufferNode - the BufferNode from where to search the next
+ * blocking BufferNode.
+ *
+ * RESULT
+ * pBufferNode - the next blocking BufferNode, or NULL if no such
+ * BufferNode exists.
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ BufferNode* pNext = NULL;
+
+ if (pStartBufferNode != NULL)
+ {
+ pNext = pStartBufferNode;
+
+ while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
+ {
+ if (pNext->getBlocker() != NULL)
+ {
+ break;
+ }
+ }
+ }
+
+ return pNext;
+}
+
+void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
+/****** SAXEventKeeperImpl/diffuse *******************************************
+ *
+ * NAME
+ * diffuse -- diffuse the notification.
+ *
+ * SYNOPSIS
+ * diffuse( pBufferNode );
+ *
+ * FUNCTION
+ * diffuse the collecting completion notification from the specific
+ * BufferNode along its parent link, until an ancestor which is not
+ * completely received is met.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode from which the notification will be
+ * diffused.
+ *
+ * RESULT
+ * empty
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ BufferNode* pParent = pBufferNode;
+
+ while(pParent->isAllReceived())
+ {
+ pParent->elementCollectorNotify();
+ pParent = (BufferNode*)pParent->getParent();
+ }
+}
+
+void SAXEventKeeperImpl::releaseElementMarkBuffer()
+/****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
+ *
+ * NAME
+ * releaseElementMarkBuffer -- releases useless ElementMarks
+ *
+ * SYNOPSIS
+ * releaseElementMarkBuffer( );
+ *
+ * FUNCTION
+ * releases each ElementMark in the releasing list
+ * m_vReleasedElementMarkBuffers.
+ * The operation differs between an ElementCollector and a Blocker.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * empty
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ m_bIsReleasing = true;
+ while (m_vReleasedElementMarkBuffers.size()>0)
+ {
+ std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
+ sal_Int32 nId = *pId;
+ m_vReleasedElementMarkBuffers.erase( pId );
+
+ ElementMark* pElementMark = findElementMarkBuffer(nId);
+
+ if (pElementMark != NULL)
+ {
+ if (cssxc::sax::ElementMarkType_TYPEOFELEMENTCOLLECTOR
+ == pElementMark->getType())
+ /*
+ * it is a EC
+ */
+ {
+ ElementCollector* pElementCollector = (ElementCollector*)pElementMark;
+
+ cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
+ bool bToModify = pElementCollector->getModify();
+
+ /*
+ * Delete the EC from the buffer node.
+ */
+ BufferNode* pBufferNode = pElementCollector->getBufferNode();
+ pBufferNode->removeElementCollector(pElementCollector);
+
+ if ( nPriority == cssxc::sax::ElementMarkPriority_PRI_BEFOREMODIFY)
+ {
+ pBufferNode->notifyBranch();
+ }
+
+ if (bToModify)
+ {
+ pBufferNode->notifyAncestor();
+ }
+
+ /*
+ * delete the ElementMark
+ */
+ pElementCollector = NULL;
+ pElementMark = NULL;
+ removeElementMarkBuffer(nId);
+
+ /*
+ * delete the BufferNode
+ */
+ diffuse(pBufferNode);
+ smashBufferNode(pBufferNode, false);
+ }
+ else
+ /*
+ * it is a Blocker
+ */
+ {
+ /*
+ * Delete the TH from the buffer node.
+ */
+ BufferNode *pBufferNode = pElementMark->getBufferNode();
+ pBufferNode->setBlocker(NULL);
+
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if (m_pCurrentBlockingBufferNode == pBufferNode)
+ {
+ /*
+ * Before forwarding, the next blocking point needs to be
+ * found.
+ */
+ m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
+
+ /*
+ * Forward the blocked events between these two STHs.
+ */
+ if (m_xNextHandler.is())
+ {
+ BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
+ BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
+
+ m_pCurrentBufferNode = pBufferNode;
+ m_pCurrentBlockingBufferNode = NULL;
+
+ m_bIsForwarding = true;
+
+ m_xXMLDocument->generateSAXEvents(
+ m_xNextHandler,
+ this,
+ pBufferNode->getXMLElement(),
+ (pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));
+
+ m_bIsForwarding = false;
+
+ m_pCurrentBufferNode = pTempCurrentBufferNode;
+ if (m_pCurrentBlockingBufferNode == NULL)
+ {
+ m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
+ }
+ }
+
+ if (m_pCurrentBlockingBufferNode == NULL &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
+ }
+ }
+
+ /*
+ * delete the ElementMark
+ */
+ pElementMark = NULL;
+ removeElementMarkBuffer(nId);
+
+ /*
+ * delete the BufferNode
+ */
+ diffuse(pBufferNode);
+ smashBufferNode(pBufferNode, true);
+ }
+ }
+ }
+
+ m_bIsReleasing = false;
+
+ if (!m_pRootBufferNode->hasAnything() &&
+ !m_pRootBufferNode->hasChildren() &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
+ }
+}
+
+void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
+/****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
+ *
+ * NAME
+ * markElementMarkBuffer -- marks an ElementMark to be released
+ *
+ * SYNOPSIS
+ * markElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * puts the ElementMark with the particular Id into the releasing list,
+ * checks whether the releasing process is runing, if not then launch
+ * this process.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark which will be released
+ *
+ * RESULT
+ * empty
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ m_vReleasedElementMarkBuffers.push_back( nId );
+ if ( !m_bIsReleasing )
+ {
+ releaseElementMarkBuffer();
+ }
+}
+
+sal_Int32 SAXEventKeeperImpl::createElementCollector(
+ sal_Int32 nSecurityId,
+ cssxc::sax::ElementMarkPriority nPriority,
+ bool bModifyElement,
+ const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+/****** SAXEventKeeperImpl/createElementCollector ****************************
+ *
+ * NAME
+ * createElementCollector -- creates a new ElementCollector on the
+ * incoming element.
+ *
+ * SYNOPSIS
+ * nId = createElementCollector( nSecurityId, nPriority,
+ * bModifyElement,
+ * xReferenceResolvedListener );
+ *
+ * FUNCTION
+ * allocs a new Id, then create an ElementCollector with this Id value.
+ * Add the new created ElementCollector to the new ElementCollecotor list.
+ *
+ * INPUTS
+ * nSecurityId - the security Id of the new ElementCollector
+ * nPriority - the prirority of the new ElementCollector
+ * bModifyElement -whether this BufferNode will modify the content of
+ * the corresponding element it works on
+ * xReferenceResolvedListener - the listener for the new ElementCollector.
+ *
+ * RESULT
+ * nId - the Id of the new ElementCollector
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ sal_Int32 nId = m_nNextElementMarkId;
+ m_nNextElementMarkId ++;
+
+ ElementCollector* pElementCollector
+ = new ElementCollector(
+ nSecurityId,
+ nId,
+ nPriority,
+ bModifyElement,
+ xReferenceResolvedListener);
+
+ m_vElementMarkBuffers.push_back( pElementCollector );
+
+ /*
+ * All the new EC to initial EC array.
+ */
+ m_vNewElementCollectors.push_back( pElementCollector );
+
+ return nId;
+}
+
+
+sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
+/****** SAXEventKeeperImpl/createBlocker *************************************
+ *
+ * NAME
+ * createBlocker -- creates a new Blocker on the incoming element.
+ *
+ * SYNOPSIS
+ * nId = createBlocker( nSecurityId );
+ *
+ * FUNCTION
+ * see NAME.
+ *
+ * INPUTS
+ * nSecurityId - the security Id of the new Blocker
+ *
+ * RESULT
+ * nId - the Id of the new Blocker
+ *
+ * HISTORY
+ * 05.01.2004 - implemented
+ *
+ * AUTHOR
+ * Michael Mi
+ * Email: michael.mi@sun.com
+ ******************************************************************************/
+{
+ sal_Int32 nId = m_nNextElementMarkId;
+ m_nNextElementMarkId ++;
+
+ OSL_ASSERT(m_pNewBlocker == NULL);
+
+ m_pNewBlocker = new ElementMark(nSecurityId, nId);
+ m_vElementMarkBuffers.push_back( m_pNewBlocker );
+
+ return nId;
+}
+
+/* XSAXEventKeeper */
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
+ throw (cssu::RuntimeException)
+{
+ return createElementCollector(
+ cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
+ cssxc::sax::ElementMarkPriority_PRI_AFTERMODIFY,
+ false,
+ NULL);
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
+ throw (cssu::RuntimeException)
+{
+ markElementMarkBuffer(id);
+}
+
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
+ throw (cssu::RuntimeException)
+{
+ return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
+ throw (cssu::RuntimeException)
+{
+ markElementMarkBuffer(id);
+}
+
+sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
+ throw (cssu::RuntimeException)
+{
+ return (m_pCurrentBlockingBufferNode != NULL);
+}
+
+cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
+ SAXEventKeeperImpl::getElement( sal_Int32 id )
+ throw (cssu::RuntimeException)
+{
+ cssu::Reference< cssxw::XXMLElementWrapper > rc;
+
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+ if (pElementMark != NULL)
+ {
+ rc = pElementMark->getBufferNode()->getXMLElement();
+ }
+
+ return rc;
+}
+
+void SAL_CALL SAXEventKeeperImpl::setElement(
+ sal_Int32 id,
+ const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
+ throw (cssu::RuntimeException)
+{
+ if (aElement.is())
+ {
+ m_xXMLDocument->rebuildIDLink(aElement);
+
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+
+ if (pElementMark != NULL)
+ {
+ BufferNode* pBufferNode = pElementMark->getBufferNode();
+ if (pBufferNode != NULL)
+ {
+ bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
+ pBufferNode->setXMLElement(aElement);
+
+ if (bIsCurrent)
+ {
+ m_xXMLDocument->setCurrentElement(aElement);
+ }
+ }
+ }
+ }
+ else
+ {
+ removeElementCollector( id );
+ }
+}
+
+cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
+ const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
+ throw (cssu::RuntimeException)
+{
+ cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;
+
+ m_xNextHandler = xNewHandler;
+ return xOldHandler;
+}
+
+rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
+ throw (cssu::RuntimeException)
+{
+ rtl::OUString rc;
+
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
+ rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
+ rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
+ rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
+ rc += printBufferNode(m_pRootBufferNode, 0);
+
+ return rc;
+}
+
+cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
+ throw (cssu::RuntimeException)
+{
+ cssu::Reference< cssxw::XXMLElementWrapper > rc;
+
+ if (m_pCurrentBlockingBufferNode != NULL)
+ {
+ rc = m_pCurrentBlockingBufferNode->getXMLElement();
+ }
+
+ return rc;
+}
+
+/* XSecuritySAXEventKeeper */
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
+ cssxc::sax::ElementMarkPriority priority,
+ sal_Bool modifyElement )
+ throw (cssu::RuntimeException)
+{
+ return createElementCollector(
+ cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
+ priority,
+ modifyElement,
+ NULL);
+}
+
+sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
+ sal_Int32 referenceId,
+ cssxc::sax::ElementMarkPriority priority )
+ throw (cssu::RuntimeException)
+{
+ sal_Int32 nId = -1;
+
+ ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
+ if (pElementCollector != NULL)
+ {
+ nId = m_nNextElementMarkId;
+ m_nNextElementMarkId ++;
+
+ ElementCollector* pClonedOne
+ = pElementCollector->clone(nId, priority);
+
+ /*
+ * add this EC into the security data buffer array.
+ */
+ m_vElementMarkBuffers.push_back(pClonedOne);
+
+ /*
+ * If the reference EC is still in initial EC array, add
+ * this cloned one into the initial EC array too.
+ */
+ if (pElementCollector->getBufferNode() == NULL)
+ {
+ m_vNewElementCollectors.push_back(pClonedOne);
+ }
+ }
+
+ return nId;
+}
+
+void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
+ throw (cssu::RuntimeException)
+{
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+ if (pElementMark != NULL)
+ {
+ pElementMark->setSecurityId(securityId);
+ }
+}
+
+
+/* XReferenceResolvedBroadcaster */
+void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
+ sal_Int32 referenceId,
+ const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
+ throw (cssu::RuntimeException)
+{
+ ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
+ if (pElementCollector != NULL)
+ {
+ pElementCollector->setReferenceResolvedListener(listener);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
+ sal_Int32 referenceId,
+ const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
+ throw (cssu::RuntimeException)
+{
+}
+
+/* XSAXEventKeeperStatusChangeBroadcaster */
+void SAL_CALL SAXEventKeeperImpl::addXSAXEventKeeperStatusChangeListener(
+ const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
+ throw (cssu::RuntimeException)
+{
+ m_xSAXEventKeeperStatusChangeListener = listener;
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeXSAXEventKeeperStatusChangeListener(
+ const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
+ throw (cssu::RuntimeException)
+{
+}
+
+/* XDocumentHandler */
+void SAL_CALL SAXEventKeeperImpl::startDocument( )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ if ( m_xNextHandler.is())
+ {
+ m_xNextHandler->startDocument();
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::endDocument( )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ if ( m_xNextHandler.is())
+ {
+ m_xNextHandler->endDocument();
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::startElement(
+ const rtl::OUString& aName,
+ const cssu::Reference< cssxs::XAttributeList >& xAttribs )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if ((m_pCurrentBlockingBufferNode == NULL) &&
+ (m_xNextHandler.is()) &&
+ (!m_bIsForwarding) &&
+ (m_pNewBlocker == NULL))
+ {
+ m_xNextHandler->startElement(aName, xAttribs);
+ }
+
+ /*
+ * If not forwarding, buffer this startElement.
+ */
+ if (!m_bIsForwarding)
+ {
+ #ifndef _USECOMPRESSEDDOCUMENTHANDLER
+ m_xDocumentHandler->startElement(aName, xAttribs);
+ #else
+ sal_Int32 nLength = xAttribs->getLength();
+ cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);
+
+ for ( int i = 0; i<nLength; ++i )
+ {
+ aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
+ aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
+ }
+
+ m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
+ #endif
+
+ }
+
+ BufferNode* pBufferNode = addNewElementMarkBuffers();
+ if (pBufferNode != NULL)
+ {
+ setCurrentBufferNode(pBufferNode);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
+
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if ((m_pCurrentBlockingBufferNode == NULL) &&
+ (m_xNextHandler.is()) &&
+ (!m_bIsForwarding))
+ {
+ m_xNextHandler->endElement(aName);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != NULL) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode) ||
+ (!m_xXMLDocument->isCurrentElementEmpty()))
+ {
+ if (!m_bIsForwarding)
+ {
+ #ifndef _USECOMPRESSEDDOCUMENTHANDLER
+ m_xDocumentHandler->endElement(aName);
+ #else
+ m_xCompressedDocumentHandler->_endElement(aName);
+ #endif
+ }
+
+ /*
+ * If the current buffer node has not notified yet, and
+ * the current buffer node is waiting for the current element,
+ * then let it notify.
+ */
+ if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
+ {
+ BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
+ m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();
+
+ pOldCurrentBufferNode->setReceivedAll();
+
+ if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
+ }
+ }
+ }
+ else
+ {
+ if (!m_bIsForwarding)
+ {
+ m_xXMLDocument->removeCurrentElement();
+ }
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ if (!m_bIsForwarding)
+ {
+ if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
+ {
+ m_xNextHandler->characters(aChars);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != NULL) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode))
+ {
+ #ifndef _USECOMPRESSEDDOCUMENTHANDLER
+ m_xDocumentHandler->characters(aChars);
+ #else
+ m_xCompressedDocumentHandler->_characters(aChars);
+ #endif
+ }
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ characters( aWhitespaces );
+}
+
+void SAL_CALL SAXEventKeeperImpl::processingInstruction(
+ const rtl::OUString& aTarget, const rtl::OUString& aData )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+ if (!m_bIsForwarding)
+ {
+ if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
+ {
+ m_xNextHandler->processingInstruction(aTarget, aData);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != NULL) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode))
+ {
+ #ifndef _USECOMPRESSEDDOCUMENTHANDLER
+ m_xDocumentHandler->processingInstruction(aTarget, aData);
+ #else
+ m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
+ #endif
+ }
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
+ throw (cssxs::SAXException, cssu::RuntimeException)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
+ throw (cssu::Exception, cssu::RuntimeException)
+{
+ sal_Int32 nLength = aArguments.getLength();
+
+ OSL_ASSERT(nLength == 1);
+
+ aArguments[0] >>= m_xXMLDocument;
+ m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
+ m_xXMLDocument, cssu::UNO_QUERY );
+ m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
+ m_xXMLDocument, cssu::UNO_QUERY );
+
+ m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
+ m_pCurrentBufferNode = m_pRootBufferNode;
+}
+
+rtl::OUString SAXEventKeeperImpl_getImplementationName ()
+ throw (cssu::RuntimeException)
+{
+ return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
+}
+
+sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
+ throw (cssu::RuntimeException)
+{
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
+}
+
+cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames( )
+ throw (cssu::RuntimeException)
+{
+ cssu::Sequence < rtl::OUString > aRet(1);
+ rtl::OUString* pArray = aRet.getArray();
+ pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+ return aRet;
+}
+#undef SERVICE_NAME
+
+cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
+ const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr)
+ throw( cssu::Exception )
+{
+ return (cppu::OWeakObject*) new SAXEventKeeperImpl();
+}
+
+/* XServiceInfo */
+rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
+ throw (cssu::RuntimeException)
+{
+ return SAXEventKeeperImpl_getImplementationName();
+}
+sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
+ throw (cssu::RuntimeException)
+{
+ return SAXEventKeeperImpl_supportsService( rServiceName );
+}
+cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
+ throw (cssu::RuntimeException)
+{
+ return SAXEventKeeperImpl_getSupportedServiceNames();
+}
+