diff options
author | Malte Timmermann <mt@openoffice.org> | 2004-07-12 12:15:31 +0000 |
---|---|---|
committer | Malte Timmermann <mt@openoffice.org> | 2004-07-12 12:15:31 +0000 |
commit | dacd1d7e88dc6d9b44c05685e0a2b256606b39c9 (patch) | |
tree | d080282db103de69bcfa3d6812677d67751f0f7d /xmlsecurity/source/framework/saxeventkeeperimpl.cxx | |
parent | 22b822e1e0528b1980830135358d609407982f63 (diff) |
libxmlsec
Diffstat (limited to 'xmlsecurity/source/framework/saxeventkeeperimpl.cxx')
-rw-r--r-- | xmlsecurity/source/framework/saxeventkeeperimpl.cxx | 1503 |
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(); +} + |