diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 16:07:07 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 16:07:07 +0000 |
commit | 8ab086b6cc054501bfbf7ef6fa509c393691e860 (patch) | |
tree | 324d51845d7f1a2f4e02a14db22fb5947137c822 /sax | |
parent | 411e68cc54ae97eebd79ae3a9cb2971b74cb2a9e (diff) |
initial import
Diffstat (limited to 'sax')
-rw-r--r-- | sax/prj/d.lst | 2 | ||||
-rw-r--r-- | sax/source/expatwrap/attrlistimpl.cxx | 233 | ||||
-rw-r--r-- | sax/source/expatwrap/attrlistimpl.hxx | 94 | ||||
-rw-r--r-- | sax/source/expatwrap/factory.hxx | 67 | ||||
-rw-r--r-- | sax/source/expatwrap/makefile.mk | 92 | ||||
-rw-r--r-- | sax/source/expatwrap/sax_expat.cxx | 1043 | ||||
-rw-r--r-- | sax/source/expatwrap/saxwriter.cxx | 736 | ||||
-rw-r--r-- | sax/source/expatwrap/xml2utf.cxx | 607 | ||||
-rw-r--r-- | sax/test/makefile.mk | 101 | ||||
-rw-r--r-- | sax/test/sax/exports.dxp | 3 | ||||
-rw-r--r-- | sax/test/sax/factory.hxx | 122 | ||||
-rw-r--r-- | sax/test/sax/makefile.mk | 99 | ||||
-rw-r--r-- | sax/test/sax/testsax.cxx | 902 | ||||
-rw-r--r-- | sax/test/sax/testwriter.cxx | 714 | ||||
-rw-r--r-- | sax/test/saxdemo.cxx | 693 | ||||
-rw-r--r-- | sax/test/testcomponent.cxx | 267 | ||||
-rw-r--r-- | sax/util/makefile.mk | 93 |
17 files changed, 5868 insertions, 0 deletions
diff --git a/sax/prj/d.lst b/sax/prj/d.lst new file mode 100644 index 000000000000..a787c3a4c3c0 --- /dev/null +++ b/sax/prj/d.lst @@ -0,0 +1,2 @@ +..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\* +..\%__SRC%\lib\*.so %_DEST%\lib%_EXT%\* diff --git a/sax/source/expatwrap/attrlistimpl.cxx b/sax/source/expatwrap/attrlistimpl.cxx new file mode 100644 index 000000000000..1d4a36c6f699 --- /dev/null +++ b/sax/source/expatwrap/attrlistimpl.cxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * $RCSfile: attrlistimpl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:12 $ + * + * 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 <vector> + +#include <assert.h> + +#include <cppuhelper/weak.hxx> + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +using namespace ::std; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::xml::sax; + +#include "attrlistimpl.hxx" + +struct TagAttribute +{ + TagAttribute() + {} + TagAttribute( const OUString &sName, const OUString &sType , const OUString &sValue ) + { + this->sName = sName; + this->sType = sType; + this->sValue = sValue; + } + + OUString sName; + OUString sType; + OUString sValue; +}; + +struct AttributeListImpl_impl +{ + AttributeListImpl_impl() + { + // performance improvement during adding + vecAttribute.reserve(20); + } + vector<struct TagAttribute> vecAttribute; +}; + + + +sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException) +{ + return m_pImpl->vecAttribute.size(); +} + + +AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) +{ + m_pImpl = new AttributeListImpl_impl; + *m_pImpl = *(r.m_pImpl); +} + +OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sName; + } + return OUString(); +} + + +OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sType; + } + return OUString(); +} + +OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sValue; + } + return OUString(); + +} + +OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sType; + } + } + return OUString(); +} + +OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sValue; + } + } + return OUString(); +} + + +Reference< XCloneable > AttributeListImpl::createClone() throw (RuntimeException) +{ + AttributeListImpl *p = new AttributeListImpl( *this ); + return Reference< XCloneable > ( (XCloneable * ) p ); +} + + + +AttributeListImpl::AttributeListImpl() +{ + m_pImpl = new AttributeListImpl_impl; +} + + + +AttributeListImpl::~AttributeListImpl() +{ + delete m_pImpl; +} + + +void AttributeListImpl::addAttribute( const OUString &sName , + const OUString &sType , + const OUString &sValue ) +{ + m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) ); +} + +void AttributeListImpl::clear() +{ + m_pImpl->vecAttribute.clear(); +} + +void AttributeListImpl::removeAttribute( const OUString &sName ) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + m_pImpl->vecAttribute.erase( ii ); + break; + } + } +} + + +void AttributeListImpl::setAttributeList( const Reference< XAttributeList > &r ) +{ + assert( r.is() ); + + sal_Int16 nMax = r->getLength(); + clear(); + m_pImpl->vecAttribute.reserve( nMax ); + + for( int i = 0 ; i < nMax ; i ++ ) { + m_pImpl->vecAttribute.push_back( TagAttribute( r->getNameByIndex( i ) , + r->getTypeByIndex( i ) , + r->getValueByIndex( i ) ) ); + } + + assert( nMax == getLength() ); +} + diff --git a/sax/source/expatwrap/attrlistimpl.hxx b/sax/source/expatwrap/attrlistimpl.hxx new file mode 100644 index 000000000000..d618e5259719 --- /dev/null +++ b/sax/source/expatwrap/attrlistimpl.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * $RCSfile: attrlistimpl.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <cppuhelper/implbase2.hxx> + + +struct AttributeListImpl_impl; + +class AttributeListImpl : + public WeakImplHelper2< XAttributeList, XCloneable > +{ +public: + AttributeListImpl(); + AttributeListImpl( const AttributeListImpl & ); + ~AttributeListImpl(); + +public: + virtual sal_Int16 SAL_CALL getLength(void) throw(RuntimeException); + virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw(RuntimeException); + virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw(RuntimeException); + virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw(RuntimeException); + virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw(RuntimeException); + virtual OUString SAL_CALL getValueByName(const OUString& aName) throw( RuntimeException); + +public: + virtual Reference< XCloneable > SAL_CALL createClone() throw(RuntimeException); + +public: + void addAttribute( const OUString &sName , const OUString &sType , const OUString &sValue ); + void clear(); + void removeAttribute( const OUString &sName ); + void setAttributeList( const Reference< XAttributeList > & ); + +private: + struct AttributeListImpl_impl *m_pImpl; +}; + diff --git a/sax/source/expatwrap/factory.hxx b/sax/source/expatwrap/factory.hxx new file mode 100644 index 000000000000..57698321b574 --- /dev/null +++ b/sax/source/expatwrap/factory.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * $RCSfile: factory.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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): _______________________________________ + * + * + ************************************************************************/ +Reference< XInterface > SAL_CALL SaxWriter_CreateInstance( + const Reference< XMultiServiceFactory > & rSMgr ) throw (Exception); +OUString SaxWriter_getServiceName(); +OUString SaxWriter_getImplementationName(); +Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw(); + + diff --git a/sax/source/expatwrap/makefile.mk b/sax/source/expatwrap/makefile.mk new file mode 100644 index 000000000000..19119165b1a1 --- /dev/null +++ b/sax/source/expatwrap/makefile.mk @@ -0,0 +1,92 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ +# +# 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): _______________________________________ +# +# +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=sax +TARGET=expatwrap +NO_BSYMBOLIC=TRUE +ENABLE_EXCEPTIONS=TRUE +# --- Settings ----------------------------------------------------- +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk +#----------------------------------------------------------- +CFLAGS += -DXML_UNICODE + +SLOFILES =\ + $(SLO)$/xml2utf.obj\ + $(SLO)$/attrlistimpl.obj\ + $(SLO)$/sax_expat.obj \ + $(SLO)$/saxwriter.obj + +# NETBSD: somewhere we have to instantiate the static data members. +# NETBSD-1.2.1 doesn't know about weak symbols so the default mechanism for GCC won't work. +# SCO and MACOSX: the linker does know about weak symbols, but we can't ignore multiple defined symbols +.IF "$(OS)"=="NETBSD" || "$(OS)"=="SCO" || "$(OS)$(COM)"=="OS2GCC" || "$(OS)"=="MACOSX" +SLOFILES+=$(SLO)$/staticmb.obj +.ENDIF + +# --- Targets ------------------------------------------------------ +.INCLUDE : target.mk + + + diff --git a/sax/source/expatwrap/sax_expat.cxx b/sax/source/expatwrap/sax_expat.cxx new file mode 100644 index 000000000000..8c9a6f170c31 --- /dev/null +++ b/sax/source/expatwrap/sax_expat.cxx @@ -0,0 +1,1043 @@ +/************************************************************************* + * + * $RCSfile: sax_expat.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <vector> + +#ifdef WIN32 +#include <malloc.h> +#else +#ifndef MACOSX +#include <alloca.h> +#endif +#endif + +#include <osl/diagnose.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <assert.h> + +#include "expat/xmlparse.h" + +using namespace ::rtl; +using namespace ::std; +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; + +#include "factory.hxx" +#include "attrlistimpl.hxx" +#include "xml2utf.hxx" + +OUString XmlNChar2OUString( const XML_Char *p , int nLen ) +{ + if( p ) { + if( sizeof( sal_Unicode ) == sizeof( XML_Char ) ) + { + return OUString( (sal_Unicode*)p,nLen); + } + else + { + sal_Unicode *pWchar = (sal_Unicode *)alloca( sizeof( sal_Unicode ) * nLen ); + for( int n = 0 ; n < nLen ; n++ ) { + pWchar[n] = (sal_Unicode) p[n]; + } + return OUString( pWchar , nLen ); + } + } + else { + return OUString(); + } +} + +OUString XmlChar2OUString( const XML_Char *p ) +{ + if( p ) { + for( int nLen = 0 ; p[nLen] ; nLen ++ ); + return XmlNChar2OUString( p , nLen ); + } + else return OUString(); +} + + +// Useful macros for correct String conversion depending on the choosen expat-mode +#ifdef XML_UNICODE +#define XML_CHAR_TO_OUSTRING(x) XmlChar2OUString(x) +#define XML_CHAR_N_TO_USTRING(x,n) XmlNChar2OUString(x,n) +#else +#define XML_CHAR_TO_OUSTRING(x) OStringToOUString(OString(x), RTL_TEXTENCODING_UTF8) +#define XML_CHAR_N_TO_OUSTRING(x,n) OStringToOUString(OString(x,n), RTL_TEXTENCODING_UTF8 ) +#endif + + +/* +* The following macro encapsulates any call to an event handler. +* It ensures, that exceptions thrown by the event handler are +* treated properly. +*/ +#define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \ + if( ! pThis->bExceptionWasThrown ) { \ + try {\ + pThis->call;\ + }\ + catch( SAXParseException &e ) {\ + pThis->callErrorHandler( pThis , e );\ + }\ + catch( SAXException &e ) {\ + pThis->callErrorHandler( pThis , SAXParseException(\ + e.Message, \ + e.Context, \ + e.WrappedException,\ + pThis->rDocumentLocator->getPublicId(),\ + pThis->rDocumentLocator->getSystemId(),\ + pThis->rDocumentLocator->getLineNumber(),\ + pThis->rDocumentLocator->getColumnNumber()\ + ) );\ + }\ + }\ + ((void)0) + +#define IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.ParserExpat" +#define SERVICE_NAME "com.sun.star.xml.sax.Parser" + +class SaxExpatParser_Impl; + + +// This class implements the external Parser interface +class SaxExpatParser : + public WeakImplHelper2< + XParser, + XServiceInfo + > +{ + +public: + SaxExpatParser(); + ~SaxExpatParser(); + +public: + + // The implementation details + static Sequence< OUString > getSupportedServiceNames_Static(void) throw (); + static OUString getImplementationName_Static() throw (); + +public: + // The SAX-Parser-Interface + virtual void SAL_CALL parseStream( const InputSource& structSource) + throw ( SAXException, + IOException, + RuntimeException); + virtual void SAL_CALL setDocumentHandler(const Reference< XDocumentHandler > & xHandler) + throw (RuntimeException); + + virtual void SAL_CALL setErrorHandler(const Reference< XErrorHandler > & xHandler) + throw (RuntimeException); + virtual void SAL_CALL setDTDHandler(const Reference < XDTDHandler > & xHandler) + throw (RuntimeException); + virtual void SAL_CALL setEntityResolver(const Reference< XEntityResolver >& xResolver) + throw (RuntimeException); + + virtual void SAL_CALL setLocale( const Locale &locale ) throw (RuntimeException); + +public: // XServiceInfo + OUString SAL_CALL getImplementationName() throw (); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw (); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (); + +private: + + SaxExpatParser_Impl *m_pImpl; + +}; + +//-------------------------------------- +// the extern interface +//--------------------------------------- +Reference< XInterface > SAL_CALL SaxExpatParser_CreateInstance( + const Reference< XMultiServiceFactory > & rSMgr ) throw(Exception) +{ + SaxExpatParser *p = new SaxExpatParser; + + return Reference< XInterface > ( (OWeakObject * ) p ); +} + + + +Sequence< OUString > SaxExpatParser::getSupportedServiceNames_Static(void) throw () +{ + Sequence<OUString> aRet(1); + aRet.getArray()[0] = SaxExpatParser::getImplementationName_Static(); + return aRet; +} + + +//--------------------------------------------- +// the implementation part +//--------------------------------------------- + + +// Entity binds all information neede for a single file +struct Entity +{ + InputSource structSource; + XML_Parser pParser; + XMLFile2UTFConverter converter; +}; + + +class SaxExpatParser_Impl +{ +public: // module scope + Mutex aMutex; + + Reference< XDocumentHandler > rDocumentHandler; + Reference< XExtendedDocumentHandler > rExtendedDocumentHandler; + + Reference< XErrorHandler > rErrorHandler; + Reference< XDTDHandler > rDTDHandler; + Reference< XEntityResolver > rEntityResolver; + Reference < XLocator > rDocumentLocator; + + + Reference < XAttributeList > rAttrList; + AttributeListImpl *pAttrList; + + // External entity stack + vector<struct Entity> vecEntity; + void pushEntity( const struct Entity &entity ) + { vecEntity.push_back( entity ); } + void popEntity() + { vecEntity.pop_back( ); } + struct Entity &getEntity() + { return vecEntity.back(); } + + + // Exception cannot be thrown through the C-XmlParser (possible resource leaks), + // therefor the exception must be saved somewhere. + SAXParseException exception; + sal_Bool bExceptionWasThrown; + + Locale locale; + +public: + // the C-Callbacks for the expat parser + void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts); + void static callbackEndElement(void *userData, const XML_Char *name); + void static callbackCharacters( void *userData , const XML_Char *s , int nLen ); + void static callbackProcessingInstruction( void *userData , + const XML_Char *sTarget , + const XML_Char *sData ); + + void static callbackUnparsedEntityDecl( void *userData , + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + + void static callbackNotationDecl( void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + + int static callbackExternalEntityRef( XML_Parser parser, + const XML_Char *openEntityNames, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + + int static callbackUnknownEncoding(void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + + void static callbackDefault( void *userData, const XML_Char *s, int len); + + void static callbackStartCDATA( void *userData ); + void static callbackEndCDATA( void *userData ); + void static callbackComment( void *userData , const XML_Char *s ); + void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e ); + +public: + void parse(); +}; + + +//--------------------------------------------- +// LocatorImpl +//--------------------------------------------- +class LocatorImpl : + public WeakImplHelper1< XLocator > +{ +public: + LocatorImpl( SaxExpatParser_Impl *p ) + { + m_pParser = p; + } + +public: //XLocator + virtual sal_Int32 SAL_CALL getColumnNumber(void) throw () + { + return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser ); + } + virtual sal_Int32 SAL_CALL getLineNumber(void) throw () + { + return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser ); + } + virtual OUString SAL_CALL getPublicId(void) throw () + { + return m_pParser->getEntity().structSource.sPublicId; + } + virtual OUString SAL_CALL getSystemId(void) throw () + { + return m_pParser->getEntity().structSource.sSystemId; + } + +private: + + SaxExpatParser_Impl *m_pParser; +}; + + + + +SaxExpatParser::SaxExpatParser( ) +{ + m_pImpl = new SaxExpatParser_Impl; + + LocatorImpl *pLoc = new LocatorImpl( m_pImpl ); + m_pImpl->rDocumentLocator = Reference< XLocator > ( pLoc ); + + // performance-Improvment. Reference is needed when calling the startTag callback. + // Handing out the same object with every call is allowed (see sax-specification) + m_pImpl->pAttrList = new AttributeListImpl; + m_pImpl->rAttrList = Reference< XAttributeList > ( m_pImpl->pAttrList ); + + m_pImpl->bExceptionWasThrown = sal_False; +} + +SaxExpatParser::~SaxExpatParser() +{ + delete m_pImpl; +} + + +/*************** +* +* parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does +* the file-specific initialization work. (During a parser run, external files may be opened) +* +****************/ +void SaxExpatParser::parseStream( const InputSource& structSource) + throw (SAXException, + IOException, + RuntimeException) +{ + // Only one text at one time + MutexGuard guard( m_pImpl->aMutex ); + + + struct Entity entity; + entity.structSource = structSource; + + if( ! entity.structSource.aInputStream.is() ) + { + throw SAXException( OUString::createFromAscii( "No input source" ) , + Reference< XInterface > () , Any() ); + } + + entity.converter.setInputStream( entity.structSource.aInputStream ); + if( entity.structSource.sEncoding.len() ) + { + entity.converter.setEncoding( + OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) ); + } + + // create parser with proper encoding + entity.pParser = XML_ParserCreate( 0 ); + if( ! entity.pParser ) + { + throw SAXException( OUString::createFromAscii( "Couldn't create parser" ) , + Reference< XInterface > (), Any() ); + } + + // set all necessary C-Callbacks + XML_SetUserData( entity.pParser , m_pImpl ); + XML_SetElementHandler( entity.pParser , + SaxExpatParser_Impl::callbackStartElement , + SaxExpatParser_Impl::callbackEndElement ); + XML_SetCharacterDataHandler( entity.pParser , SaxExpatParser_Impl::callbackCharacters ); + XML_SetProcessingInstructionHandler(entity.pParser , + SaxExpatParser_Impl::callbackProcessingInstruction ); + XML_SetUnparsedEntityDeclHandler( entity.pParser, + SaxExpatParser_Impl::callbackUnparsedEntityDecl ); + XML_SetNotationDeclHandler( entity.pParser, SaxExpatParser_Impl::callbackNotationDecl ); + XML_SetExternalEntityRefHandler( entity.pParser, + SaxExpatParser_Impl::callbackExternalEntityRef); + XML_SetUnknownEncodingHandler( entity.pParser, SaxExpatParser_Impl::callbackUnknownEncoding ,0); + + if( m_pImpl->rExtendedDocumentHandler.is() ) { + + // These handlers just delegate calls to the ExtendedHandler. If no extended handler is + // given, these callbacks can be ignored + XML_SetDefaultHandlerExpand( entity.pParser, SaxExpatParser_Impl::callbackDefault ); + XML_SetCommentHandler( entity.pParser, SaxExpatParser_Impl::callbackComment ); + XML_SetCdataSectionHandler( entity.pParser , + SaxExpatParser_Impl::callbackStartCDATA , + SaxExpatParser_Impl::callbackEndCDATA ); + } + + + m_pImpl->exception = SAXParseException(); + m_pImpl->pushEntity( entity ); + try + { + // start the document + if( m_pImpl->rDocumentHandler.is() ) { + m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator ); + m_pImpl->rDocumentHandler->startDocument(); + } + + m_pImpl->parse(); + + // finish document + if( m_pImpl->rDocumentHandler.is() ) { + m_pImpl->rDocumentHandler->endDocument(); + } + } + +// catch( SAXParseException & ) +// { +// m_pImpl->popEntity(); +// XML_ParserFree( entity.pParser ); +// throw; +// } + catch( SAXException & ) + { + m_pImpl->popEntity(); + XML_ParserFree( entity.pParser ); + throw; + } + catch( IOException & ) + { + m_pImpl->popEntity(); + XML_ParserFree( entity.pParser ); + throw; + } + catch( RuntimeException & ) + { + m_pImpl->popEntity(); + XML_ParserFree( entity.pParser ); + throw; + } + + m_pImpl->popEntity(); + XML_ParserFree( entity.pParser ); +} + +void SaxExpatParser::setDocumentHandler(const Reference< XDocumentHandler > & xHandler) + throw (RuntimeException) +{ + m_pImpl->rDocumentHandler = xHandler; + m_pImpl->rExtendedDocumentHandler = + Reference< XExtendedDocumentHandler >( xHandler , UNO_QUERY ); +} + +void SaxExpatParser::setErrorHandler(const Reference< XErrorHandler > & xHandler) + throw (RuntimeException) +{ + m_pImpl->rErrorHandler = xHandler; +} + +void SaxExpatParser::setDTDHandler(const Reference< XDTDHandler > & xHandler) + throw (RuntimeException) +{ + m_pImpl->rDTDHandler = xHandler; +} + +void SaxExpatParser::setEntityResolver(const Reference < XEntityResolver > & xResolver) + throw (RuntimeException) +{ + m_pImpl->rEntityResolver = xResolver; +} + + +void SaxExpatParser::setLocale( const Locale & locale ) throw (RuntimeException) +{ + m_pImpl->locale = locale; +} + +OUString SaxExpatParser::getImplementationName_Static() throw () +{ + return OUString::createFromAscii( IMPLEMENTATION_NAME ); +} + +// XServiceInfo +OUString SaxExpatParser::getImplementationName() throw () +{ + return OUString::createFromAscii( IMPLEMENTATION_NAME ); +} + +// XServiceInfo +sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw () +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + + return sal_False; +} + +// XServiceInfo +Sequence< OUString > SaxExpatParser::getSupportedServiceNames(void) throw () +{ + + Sequence<OUString> seq(1); + seq.getArray()[0] = OUString::createFromAscii( SERVICE_NAME ); + return seq; +} + + +/*--------------------------------------- +* +* Helper functions and classes +* +* +*-------------------------------------------*/ +OUString getErrorMessage( XML_Error xmlE, OUString sSystemId , sal_Int32 nLine ) +{ + OUString Message; + if( XML_ERROR_NONE == xmlE ) { + Message = OUString::createFromAscii( "No" ); + } + else if( XML_ERROR_NO_MEMORY == xmlE ) { + Message = OUString::createFromAscii( "no memory" ); + } + else if( XML_ERROR_SYNTAX == xmlE ) { + Message = OUString::createFromAscii( "syntax" ); + } + else if( XML_ERROR_NO_ELEMENTS == xmlE ) { + Message = OUString::createFromAscii( "no elements" ); + } + else if( XML_ERROR_INVALID_TOKEN == xmlE ) { + Message = OUString::createFromAscii( "invalid token" ); + } + else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) { + Message = OUString::createFromAscii( "unclosed token" ); + } + else if( XML_ERROR_PARTIAL_CHAR == xmlE ) { + Message = OUString::createFromAscii( "partial char" ); + } + else if( XML_ERROR_TAG_MISMATCH == xmlE ) { + Message = OUString::createFromAscii( "tag mismatch" ); + } + else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) { + Message = OUString::createFromAscii( "duplicate attribute" ); + } + else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) { + Message = OUString::createFromAscii( "junk after doc element" ); + } + else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) { + Message = OUString::createFromAscii( "parameter entity reference" ); + } + else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) { + Message = OUString::createFromAscii( "undefined entity" ); + } + else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) { + Message = OUString::createFromAscii( "recursive entity reference" ); + } + else if( XML_ERROR_ASYNC_ENTITY == xmlE ) { + Message = OUString::createFromAscii( "async entity" ); + } + else if( XML_ERROR_BAD_CHAR_REF == xmlE ) { + Message = OUString::createFromAscii( "bad char reference" ); + } + else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) { + Message = OUString::createFromAscii( "binary entity reference" ); + } + else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) { + Message = OUString::createFromAscii( "attribute external entity reference" ); + } + else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) { + Message = OUString::createFromAscii( "misplaced xml processing instruction" ); + } + else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) { + Message = OUString::createFromAscii( "unknown encoding" ); + } + else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) { + Message = OUString::createFromAscii( "incorrect encoding" ); + } + else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) { + Message = OUString::createFromAscii( "unclosed cdata section" ); + } + else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) { + Message = OUString::createFromAscii( "external entity reference" ); + } + else if( XML_ERROR_NOT_STANDALONE == xmlE ) { + Message = OUString::createFromAscii( "not standalone" ); + } + + OUString str = OUString::createFromAscii( "[" ); + str += sSystemId; + str += OUString::createFromAscii( " line " ); + str += OUString::valueOf( nLine ); + str += OUString::createFromAscii( "]: " ); + str += Message; + str += OUString::createFromAscii( "error" ); + + return str; +} + + +// starts parsing with actual parser ! +void SaxExpatParser_Impl::parse( ) +{ + const int nBufSize = 16*1024; + + int nRead = nBufSize; + Sequence< sal_Int8 > seqOut(nBufSize); + + while( nRead ) { + nRead = getEntity().converter.readAndConvert( seqOut , nBufSize ); + + if( ! nRead ) { + XML_Parse( getEntity().pParser , ( const char * ) seqOut.getArray() , 0 , 1 ); + break; + } + + sal_Bool bContinue = XML_Parse( getEntity().pParser ,(const char *) seqOut.getArray(),nRead,0); + + if( ! bContinue || this->bExceptionWasThrown ) { + + // Error during parsing ! + XML_Error xmlE = XML_GetErrorCode( getEntity().pParser ); + OUString sSystemId = rDocumentLocator->getSystemId(); + sal_Int32 nLine = rDocumentLocator->getLineNumber(); + + SAXParseException aExcept( + getErrorMessage(xmlE , sSystemId, nLine) , + Reference< XInterface >(), + Any( &exception , getCppuType( &exception) ), + rDocumentLocator->getPublicId(), + rDocumentLocator->getSystemId(), + rDocumentLocator->getLineNumber(), + rDocumentLocator->getColumnNumber() + ); + + if( rErrorHandler.is() ) { + + // error handler is set, so the handler may throw the exception + Any a; + a <<= aExcept; + rErrorHandler->fatalError( a ); + } + + // Error handler has not thrown an exception, but parsing cannot go on, + // so an exception MUST be thrown. + throw aExcept; + } // if( ! bContinue ) + } // while +} + +//------------------------------------------ +// +// The C-Callbacks +// +//----------------------------------------- +void SaxExpatParser_Impl::callbackStartElement( void *pvThis , + const XML_Char *pwName , + const XML_Char **awAttributes ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + if( pImpl->rDocumentHandler.is() ) { + + int i = 0; + pImpl->pAttrList->clear(); + + while( awAttributes[i] ) { + assert( awAttributes[i+1] ); + pImpl->pAttrList->addAttribute( + XML_CHAR_TO_OUSTRING( awAttributes[i] ) , + OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA") ) , // expat doesn't know types + XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) ); + i +=2; + } + + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( + pImpl , + rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) , + pImpl->rAttrList ) ); + } +} + +void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + if( pImpl->rDocumentHandler.is() ) { + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, + rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) ); + } +} + + +void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + if( pImpl->rDocumentHandler.is() ) { + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl , + rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) ); + } +} + +void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis, + const XML_Char *sTarget , + const XML_Char *sData ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + if( pImpl->rDocumentHandler.is() ) { + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl , + rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ), + XML_CHAR_TO_OUSTRING( sData ) ) ); + } +} + + +void SaxExpatParser_Impl::callbackUnparsedEntityDecl(void *pvThis , + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + if( pImpl->rDTDHandler.is() ) { + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( + pImpl , + rDTDHandler->unparsedEntityDecl( + XML_CHAR_TO_OUSTRING( entityName ), + XML_CHAR_TO_OUSTRING( publicId ) , + XML_CHAR_TO_OUSTRING( systemId ) , + XML_CHAR_TO_OUSTRING( notationName ) ) ); + } +} + +void SaxExpatParser_Impl::callbackNotationDecl( void *pvThis, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + if( pImpl->rDTDHandler.is() ) { + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, + rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) , + XML_CHAR_TO_OUSTRING( publicId ) , + XML_CHAR_TO_OUSTRING( systemId ) ) ); + } + +} + + + +int SaxExpatParser_Impl::callbackExternalEntityRef( XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) +{ + sal_Bool bOK = sal_True; + InputSource source; + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)XML_GetUserData( parser )); + + struct Entity entity; + + if( pImpl->rEntityResolver.is() ) { + try + { + entity.structSource = pImpl->rEntityResolver->resolveEntity( + XML_CHAR_TO_OUSTRING( publicId ) , + XML_CHAR_TO_OUSTRING( systemId ) ); + } + catch( SAXParseException & e ) + { + pImpl->exception = e; + bOK = sal_False; + } + catch( SAXException & e ) + { + pImpl->exception = SAXParseException( + e.Message , e.Context , e.WrappedException , + pImpl->rDocumentLocator->getPublicId(), + pImpl->rDocumentLocator->getSystemId(), + pImpl->rDocumentLocator->getLineNumber(), + pImpl->rDocumentLocator->getColumnNumber() ); + bOK = sal_False; + } + } + + if( entity.structSource.aInputStream.is() ) { + entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 ); + if( ! entity.pParser ) + { + return sal_False; + } + + entity.converter.setInputStream( entity.structSource.aInputStream ); + pImpl->pushEntity( entity ); + try + { + pImpl->parse(); + } + catch( SAXParseException & e ) + { + pImpl->exception = e; + bOK = sal_False; + } + catch( IOException &e ) + { + pImpl->exception.WrappedException <<= e; + bOK = sal_False; + } + catch( RuntimeException &e ) + { + pImpl->exception.WrappedException <<=e; + bOK = sal_False; + } + + pImpl->popEntity(); + + XML_ParserFree( entity.pParser ); + } + + return bOK; +} + +int SaxExpatParser_Impl::callbackUnknownEncoding(void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info) +{ + return 0; +} + +void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, + rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) ); +} + +void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, + rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) ); +} + +void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() ); +} + + +void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl , + const SAXParseException & e ) +{ + try + { + if( pImpl->rErrorHandler.is() ) { + Any a; + a <<= e; + pImpl->rErrorHandler->error( a ); + } + else { + pImpl->exception = e; + pImpl->bExceptionWasThrown = sal_True; + } + } + catch( SAXParseException & ex ) { + pImpl->exception = ex; + pImpl->bExceptionWasThrown = sal_True; + } + catch( SAXException & ex ) { + pImpl->exception = SAXParseException( + ex.Message, + ex.Context, + ex.WrappedException, + pImpl->rDocumentLocator->getPublicId(), + pImpl->rDocumentLocator->getSystemId(), + pImpl->rDocumentLocator->getLineNumber(), + pImpl->rDocumentLocator->getColumnNumber() + ); + pImpl->bExceptionWasThrown = sal_True; + } +} + +void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis ) +{ + SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis); + + CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() ); +} + + + +extern "C" +{ + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + + +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + Reference< XRegistryKey > xKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey ) ); + + Reference< XRegistryKey > xNewKey = xKey->createKey( + OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ); + xNewKey->createKey( OUString::createFromAscii( SERVICE_NAME ) ); + + xNewKey = xKey->createKey( OUString::createFromAscii("/") + + SaxWriter_getImplementationName()+ + OUString::createFromAscii( "/UNO/SERVICES" ) ); + xNewKey->createKey( SaxWriter_getServiceName() ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSHURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} + + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + void * pRet = 0; + + if (pServiceManager ) + { + Reference< XSingleServiceFactory > xRet; + Reference< XMultiServiceFactory > xSMgr = + reinterpret_cast< XMultiServiceFactory * > ( pServiceManager ); + + OUString aImplementationName = OUString::createFromAscii( pImplName ); + + if (aImplementationName == + OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ) ) + { + xRet = createSingleFactory( xSMgr, aImplementationName, + SaxExpatParser_CreateInstance, + SaxExpatParser::getSupportedServiceNames_Static() ); + } + else if ( aImplementationName == SaxWriter_getImplementationName() ) + { + xRet = createSingleFactory( xSMgr, aImplementationName, + SaxWriter_CreateInstance, + SaxWriter_getSupportedServiceNames() ); + } + + if (xRet.is()) + { + xRet->acquire(); + pRet = xRet.get(); + } + } + + return pRet; +} + + +} + diff --git a/sax/source/expatwrap/saxwriter.cxx b/sax/source/expatwrap/saxwriter.cxx new file mode 100644 index 000000000000..b4844d18c740 --- /dev/null +++ b/sax/source/expatwrap/saxwriter.cxx @@ -0,0 +1,736 @@ +/************************************************************************* + * + * $RCSfile: saxwriter.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <string.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> + +#include <com/sun/star/io/XActiveDataSource.hpp> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/implbase3.hxx> + +#include <rtl/strbuf.hxx> + +#include <assert.h> + +using namespace ::rtl; +using namespace ::std; +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; + +#include "factory.hxx" +#include "xml2utf.hxx" + +#define LINEFEED 10 + +/****** +* +* +* Character conversion functions +* +* +*****/ + + +/***** +* +* Does special conversions (beside encoding) that is needed for xml. E.g. &<>"' plus some more are +* special characters in XML that need to be transformed +* +* @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab) +* Set this to true, if you want to perform this special conversion +* +****/ +sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) +{ + sal_Int32 nLen = 0; + const sal_Int8 *pArray = seq.getConstArray(); + + + for( int i = 0 ; i < seq.getLength() ; i ++ ) { + + sal_Int8 c = pArray[i]; + if( '&' == c ) { // resemble to & + nLen += 5; + } + else if( '<' == c ) { + nLen += 4; // < + } + else if( '>' == c ) { + nLen += 4; // > + } + else if( 39 == c ) { // 39 == ''' + nLen += 6; // ' + } + else if( '"' == c ) { + nLen += 6; // " + } + else if( 13 == c ) { + nLen += 6; // 
 + } + else if( bConvertAll && LINEFEED == c ) { + nLen += 6; + } + else if( bConvertAll && 9 == c ) { + nLen += 6; + } + else { + nLen ++; + } + } + + return nLen; +} + + +inline sal_Int32 getFirstLineBreak( const Sequence<sal_Int8> & seq) +{ + const sal_Int8 *pSource = seq.getConstArray(); + + sal_Int32 nLen = seq.getLength(); + for( int n = 0; n < nLen ; n ++ ) + { + if( LINEFEED == pSource[n] ) { + return n; + } + } + return -1; +} + +inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8> & seq) +{ + const sal_Int8 *pSource = seq.getConstArray(); + sal_Int32 nLen = seq.getLength(); + + for( int n = nLen-1; n >= 0 ; n -- ) + { + if( LINEFEED == pSource[n] ) { + return n; + } + } + return -1; +} + + +class SAXWriter : + public WeakImplHelper3< + XActiveDataSource, + XExtendedDocumentHandler, + XServiceInfo > +{ +public: + SAXWriter( ) : + m_nMaxColumn(72), + m_bForceLineBreak(sal_False), + m_bAllowLineBreak(sal_False), + m_unicode2utf8( RTL_TEXTENCODING_UTF8 ) + {} + +public: // XActiveDataSource + virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) + throw (RuntimeException) + { + m_out = aStream; + m_bDocStarted = sal_False; + m_nLevel = 0; + m_bIsCDATA = sal_False; + m_nColumn = 0; + } + virtual Reference< XOutputStream > SAL_CALL getOutputStream(void) + throw(RuntimeException) + { return m_out; } + +public: // XDocumentHandler + virtual void SAL_CALL startDocument(void) + throw(SAXException, RuntimeException); + + virtual void SAL_CALL endDocument(void) + throw(SAXException, RuntimeException); + + virtual void SAL_CALL startElement(const OUString& aName, + const Reference< XAttributeList > & xAttribs) + throw (SAXException, RuntimeException); + + virtual void SAL_CALL endElement(const OUString& aName) + throw(SAXException, RuntimeException); + + virtual void SAL_CALL characters(const OUString& aChars) + throw(SAXException, RuntimeException); + + virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) + throw(SAXException, RuntimeException); + virtual void SAL_CALL processingInstruction(const OUString& aTarget, + const OUString& aData) + throw(SAXException, RuntimeException); + virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) + throw(SAXException, RuntimeException); + +public: // XExtendedDocumentHandler + virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException); + virtual void SAL_CALL endCDATA(void) throw(RuntimeException); + virtual void SAL_CALL comment(const OUString& sComment) + throw(SAXException, RuntimeException); + virtual void SAL_CALL unknown(const OUString& sString) + throw(SAXException, RuntimeException); + virtual void SAL_CALL allowLineBreak(void) + throw(SAXException,RuntimeException); + +public: // XServiceInfo + OUString SAL_CALL getImplementationName() throw(); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); + +private: + + void doIndent( Sequence<sal_Int8> &); + void writeSequence( const Sequence<sal_Int8> & seq ); + + inline void pushStartElement() + { + if( m_seqStartElement.getLength() ) + { + writeSequence( m_seqStartElement ); + m_seqStartElement = Sequence < sal_Int8 > (); + } + } + + Sequence < sal_Int8 > ustring2UTF8( const OUString &sValue ) + { + return m_unicode2utf8.convert( sValue ); + } + + Sequence < sal_Int8 > utf8ToXML( const Sequence< sal_Int8 > & , sal_Bool bConvertAll ); + + /**** + * @param bConvertAll TRUE, when LINEFEED plus tab shall also be normalized + * sal_False otherwise + * + ****/ + Sequence < sal_Int8 > ustring2XML( const OUString &sValue , sal_Bool bConvertAll ) + { + return utf8ToXML( ustring2UTF8( sValue ) , bConvertAll ); + } + + + Unicode2TextConverter m_unicode2utf8; + Reference< XOutputStream > m_out; + Sequence < sal_Int8 > m_seqStartElement; + + // Status information + sal_Bool m_bDocStarted; + sal_Bool m_bIsCDATA; + sal_Bool m_bForceLineBreak; + sal_Bool m_bAllowLineBreak; + sal_Int32 m_nLevel; + sal_Int32 m_nColumn; + sal_Int32 m_nMaxColumn; +}; + + +//-------------------------------------- +// the extern interface +//--------------------------------------- +Reference < XInterface > SAL_CALL SaxWriter_CreateInstance( + const Reference < XMultiServiceFactory > & rSMgr ) + throw (Exception) +{ + SAXWriter *p = new SAXWriter; + return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) ); +} + +OUString SaxWriter_getServiceName() +{ + return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ); +} + +OUString SaxWriter_getImplementationName() +{ + return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" ); +} + +Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw() +{ + Sequence<OUString> aRet(1); + aRet.getArray()[0] = SaxWriter_getImplementationName(); + return aRet; +} + + +Sequence < sal_Int8 > SAXWriter::utf8ToXML( const Sequence<sal_Int8> & seqSource , sal_Bool bConvertAll ) +{ + Sequence< sal_Int8 > seqTarget( CalcXMLLen( seqSource , bConvertAll ) ); + sal_Int32 nMaxSource = seqSource.getLength(); + const sal_Int8 *pSource = seqSource.getConstArray(); + sal_Int8 *pTarget = seqTarget.getArray(); + sal_Int32 nTarget = 0; + + for( int nSource = 0 ; nSource < nMaxSource ; nSource ++ ) { + sal_Int8 c = pSource[nSource]; + if( '&' == c ) { // resemble to & + memcpy( &(pTarget[nTarget]) , "&" , 5 ); + nTarget += 5; + } + else if( '<' == c ) { + memcpy( &(pTarget[nTarget]) , "<" , 4 ); + nTarget += 4; // < + } + else if( '>' == c ) { + memcpy( &(pTarget[nTarget]) , ">" , 4 ); + nTarget += 4; // > + } + else if( 39 == c ) { // 39 == ''' + memcpy( &(pTarget[nTarget]) , "'" , 6 ); + nTarget += 6; // ' + } + else if( '"' == c ) { + memcpy( &(pTarget[nTarget]) , """ , 6 ); + nTarget += 6; // " + } + else if( 13 == c ) { + memcpy( &(pTarget[nTarget]) , "
" , 6 ); + nTarget += 6; + } + else if( LINEFEED == c && bConvertAll ) { + memcpy( &(pTarget[nTarget]) , "
" , 6 ); + nTarget += 6; + } + else if( 9 == c && bConvertAll ) { + memcpy( &(pTarget[nTarget]) , "	" , 6 ); + nTarget += 6; + } + else { + pTarget[nTarget] = c; + nTarget ++; + } + } + return seqTarget; +} + + +void SAXWriter::doIndent( Sequence<sal_Int8> &seq ) +{ + sal_Int32 nLength = getFirstLineBreak( seq ); + nLength = ( nLength >= 0 ) ? nLength : seq.getLength(); + if( ( m_bForceLineBreak ) || + ( m_bAllowLineBreak && nLength + m_nColumn > m_nMaxColumn ) + ) { + + // write the linebreaks ! + Sequence<sal_Int8> seqIndent( m_nLevel + 1 ); + seqIndent.getArray()[0] = 10; + memset( &(seqIndent.getArray()[1] ) , 32 , m_nLevel ); + writeSequence( seqIndent ); + + // remove one leading space in the sequence + if( seq.getLength() && 32 == seq.getArray()[0] ) { + memmove( seq.getArray() , &(seq.getArray()[1]) , seq.getLength() -1 ); + seq.realloc( seq.getLength()-1 ); + } + + } + + m_bForceLineBreak = sal_False; + m_bAllowLineBreak = sal_False; +} + + +/******** +* write through to the output stream and counts columns +* +*****/ +void SAXWriter::writeSequence( const Sequence<sal_Int8> & seq ) +{ + + sal_Int32 nPos = getLastLineBreak( seq ); + try + { + m_out->writeBytes( seq ); + } + catch( IOException & e ) + { + Any a; + a <<= e; + throw SAXException( + OUString::createFromAscii( "io exception during writing" ), + Reference< XInterface > (), + a ); + } + + if( nPos >= 0 ) { + m_nColumn = seq.getLength() - (nPos+1); + } + else { + m_nColumn += seq.getLength(); + } +} + + + + +// XServiceInfo +OUString SAXWriter::getImplementationName() throw() +{ + return SaxWriter_getImplementationName(); +} + +// XServiceInfo +sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw() +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + + return sal_False; +} + +// XServiceInfo +Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw () +{ + Sequence<OUString> seq(1); + seq.getArray()[0] = SaxWriter_getServiceName(); + return seq; +} + + + +void SAXWriter::startDocument() throw(SAXException, RuntimeException ) +{ + if( m_bDocStarted || ! m_out.is() ) { + throw SAXException(); + } + m_bDocStarted = sal_True; + const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; + const int nLen = strlen( pc ); + Sequence<sal_Int8> seqWrite( nLen+1 ); + memcpy( seqWrite.getArray() , pc , nLen ); + seqWrite.getArray()[nLen] = LINEFEED; + writeSequence( seqWrite ); +} + + +void SAXWriter::endDocument(void) throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted ) + { + throw SAXException(); + } + if( m_nLevel ) { + throw SAXException( + OUString::createFromAscii( "unexpected end of document" ), + Reference< XInterface >() , Any() ); + } + m_out->closeOutput(); +} + + +void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs) + throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted ) + { + throw SAXException(); + } + if( m_bIsCDATA ) + { + throw SAXException(); + } + pushStartElement(); + + sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0; + + OStringBuffer str(64 *( nAttribCount+1) ); + str.append( "<" ); + + // Tags may only contain ascii chars ! + str.append( OUStringToOString( aName.getStr() , RTL_TEXTENCODING_UTF8 ) ); + + for( int n = 0 ; n < nAttribCount ; n ++ ) { + str.append( " " ); + str.append( OUStringToOString( xAttribs->getNameByIndex( n ) , RTL_TEXTENCODING_UTF8 ) ); + str.append( "=\"" ); + + Sequence<sal_Int8> seq = ustring2XML( xAttribs->getValueByIndex( n ) , sal_True ); + str.append( ( const sal_Char * ) seq.getConstArray() , seq.getLength() ); + str.append( "\"" ); + } + + // preparing for empty tag + str.append( ">" ); + + Sequence<sal_Int8> seqWrite( str.getLength() ); + memcpy( seqWrite.getArray() , str.getStr() , str.getLength() ); + + doIndent( seqWrite ); + + m_seqStartElement = seqWrite; + + m_nLevel ++; +} + +void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException) +{ + if( ! m_bDocStarted ) { + throw SAXException (); + } + m_nLevel --; + + if( m_nLevel < 0 ) { + throw SAXException(); + } + + if( m_seqStartElement.getLength() ) + { + m_seqStartElement.realloc( m_seqStartElement.getLength() + 1 ); + + sal_Int8 *p = m_seqStartElement.getArray(); + p[m_seqStartElement.getLength()-2] = '/'; + p[m_seqStartElement.getLength()-1] = '>'; + writeSequence( m_seqStartElement ); + m_seqStartElement = Sequence< sal_Int8 > (); + } + else { + // only ascii chars allowed + sal_Int32 nLen = aName.getLength(); + Sequence< sal_Int8 > seqWrite( nLen + 3 ); + + sal_Int8 *p = seqWrite.getArray(); + sal_Unicode *pStr = (sal_Unicode * )aName.getStr(); + + p[0] = '<'; + p[1] = '/'; + for( sal_Int32 i = 0 ; i < nLen ; i ++ ) + { + p[2+i] = (sal_Int8) pStr[i]; + } + p[nLen+2] = '>'; + + doIndent( seqWrite ); + writeSequence( seqWrite ); + } +} + +void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted ) + { + throw SAXException(); + } + pushStartElement(); + + if( m_bIsCDATA ) { + Sequence<sal_Int8> seqWrite = ustring2UTF8( aChars); + writeSequence( seqWrite ); + } + else { + Sequence<sal_Int8> seqWrite = ustring2XML( aChars , sal_False ); + doIndent( seqWrite ); + writeSequence( seqWrite ); + } +} + + +void SAXWriter::ignorableWhitespace(const OUString& aWhitespaces) throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted ) + { + throw SAXException (); + } + + m_bForceLineBreak = sal_True; +} + +void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData) + throw (SAXException, RuntimeException) +{ + if( ! m_bDocStarted || m_bIsCDATA ) + { + throw SAXException(); + } + + pushStartElement(); + + OStringBuffer str( 128 ); + str.append( "<?" ); + str.append( OUStringToOString( aTarget , RTL_TEXTENCODING_UTF8 ) ); + str.append( " " ); + str.append( OUStringToOString( aData , RTL_TEXTENCODING_UTF8 ) ); // only ascii chars allowed + str.append( "?>" ); + + Sequence<sal_Int8> seq( str.getLength() ); + memcpy( seq.getArray() , str.getStr() , str.getLength() ); + + doIndent( seq ); + writeSequence( seq ); +} + + +void SAXWriter::setDocumentLocator(const Reference< XLocator >& xLocator) + throw (SAXException, RuntimeException) +{ + +} + +void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted || m_bIsCDATA) + { + throw SAXException (); + } + + pushStartElement(); + + Sequence < sal_Int8 > seq( ( sal_Int8 * ) "<![CDATA[" , 9 ); + + doIndent( seq ); + writeSequence( seq ); + m_bIsCDATA = sal_True; +} + +void SAXWriter::endCDATA(void) throw (RuntimeException) +{ + if( ! m_bDocStarted | ! m_bIsCDATA) + { + throw SAXException(); + } + + pushStartElement(); + Sequence<sal_Int8> seq( ( sal_Int8 * ) "]]>" , 3 ); + + doIndent( seq ); + writeSequence( seq ); + m_bIsCDATA = sal_False; +} + + +void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException) +{ + if( ! m_bDocStarted || m_bIsCDATA ) + { + throw SAXException(); + } + + pushStartElement(); + + Sequence<sal_Int8> seq = ustring2XML( sComment , sal_False ); + + Sequence<sal_Int8> seqWrite( seq.getLength() + 7 ); + sal_Int8 *p = seqWrite.getArray(); + p[0] = '<'; + p[1] = '!'; + p[2] = '-'; + p[3] = '-'; + memcpy( &(p[4]) , seq.getConstArray() , seq.getLength() ); + p[4+seq.getLength()] = '-'; + p[5+seq.getLength()] = '-'; + p[6+seq.getLength()] = '>'; + + doIndent( seqWrite ); + writeSequence( seqWrite ); +} + + +void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException) +{ + if( ! m_bDocStarted || m_bAllowLineBreak ) { + throw SAXException(); + } + + m_bAllowLineBreak = sal_True; +} + +void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException) +{ + + if( ! m_bDocStarted ) + { + throw SAXException (); + } + if( m_bIsCDATA ) + { + throw SAXException(); + } + + pushStartElement(); + + OString str = OUStringToOString( sString , RTL_TEXTENCODING_UTF8 ); + + Sequence<sal_Int8> seq( str.getLength() ); + memcpy( seq.getArray() , str.getStr() , str.getLength() ); + + doIndent( seq ); + writeSequence( seq ); +} + + diff --git a/sax/source/expatwrap/xml2utf.cxx b/sax/source/expatwrap/xml2utf.cxx new file mode 100644 index 000000000000..a87cefab493a --- /dev/null +++ b/sax/source/expatwrap/xml2utf.cxx @@ -0,0 +1,607 @@ +/************************************************************************* + * + * $RCSfile: xml2utf.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <string.h> +#include <assert.h> + +#include <sal/types.h> + +#include <rtl/textenc.h> +#include <rtl/tencinfo.h> + + +#include <com/sun/star/io/XInputStream.hpp> + +using namespace rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; + +#include "xml2utf.hxx" + + +sal_Int32 XMLFile2UTFConverter::readAndConvert( Sequence<sal_Int8> &seq , sal_Int32 nMaxToRead ) + throw ( IOException, NotConnectedException , BufferSizeExceededException , RuntimeException ) +{ + + Sequence<sal_Int8> seqIn; + + if( ! m_in.is() ) { + throw NotConnectedException(); + } + if( ! m_bStarted ) { + nMaxToRead = Max( 512 , nMaxToRead ); // it should be possible to find the encoding attribute + // within the first 512 bytes == 128 chars in UCS-4 + } + + sal_Int32 nRead; + Sequence< sal_Int8 > seqStart; + while( sal_True ) + { + nRead = m_in->readSomeBytes( seq , nMaxToRead ); + + if( nRead + seqStart.getLength()) + { + // if nRead is 0, the file is already eof. + if( ! m_bStarted && nRead ) + { + // ensure that enough data is available to parse encoding + if( seqStart.getLength() ) + { + seq.realloc( seqStart.getLength() + seq.getLength() ); + memcpy( (sal_Int8*)seq.getConstArray() + seqStart.getLength() , + seq.getConstArray() , + seq.getLength() ); + memcpy( (sal_Int8*)seq.getConstArray() , + seqStart.getConstArray(), + seqStart.getLength() ); + } + + // autodetection with the first bytes + if( ! isEncodingRecognizable( seq ) ) + { + seqStart.realloc( seqStart.getLength() + seq.getLength() ); + memcpy( (sal_Int8*)seqStart.getConstArray() + seqStart.getLength(), + seq.getConstArray(), + seq.getLength()); + // read more ! + continue; + } + if( scanForEncoding( seq ) || m_sEncoding.getLength() ) { + // initialize decoding + initializeDecoding(); + } + nRead = seq.getLength(); + seqStart = Sequence < sal_Int8 > (); + } + + // do the encoding + if( m_pText2Unicode && m_pUnicode2Text && + m_pText2Unicode->canContinue() && m_pUnicode2Text->canContinue() ) { + + Sequence<sal_Unicode> seqUnicode = m_pText2Unicode->convert( seq ); + seq = m_pUnicode2Text->convert( seqUnicode.getConstArray(), seqUnicode.getLength() ); + } + + if( ! m_bStarted ) + { + // it must now be ensured, that no encoding attribute exist anymore + // ( otherwise the expat-Parser will crash ) + // This must be done after decoding ! + // ( e.g. Files decoded in ucs-4 cannot be read properly ) + m_bStarted = sal_True; + removeEncoding( seq ); + } + nRead = seq.getLength(); + } + + break; + } + return nRead; +} + + +XMLFile2UTFConverter::~XMLFile2UTFConverter() +{ + if( m_pText2Unicode ) + delete m_pText2Unicode; + if( m_pUnicode2Text ) + delete m_pUnicode2Text; +} + + +void XMLFile2UTFConverter::removeEncoding( Sequence<sal_Int8> &seq ) +{ + const sal_Int8 *pSource = seq.getArray(); + if( ! strncmp( (const char * ) pSource , "<?xml" , 4) ) + { + + // scan for encoding + OString str( (sal_Char * ) pSource , seq.getLength() ); + + // cut sequence to first line break + // find first line break; + int nMax = str.indexOf( 10 ); + if( nMax >= 0 ) + { + str = str.copy( 0 , nMax ); + } + + int nFound = str.indexOf( " encoding" ); + if( nFound < str.getLength() ) { + int nStop; + int nStart = str.indexOf( "\"" , nFound ); + if( nStart < 0 || str.indexOf( "'" , nFound ) < nStart ) + { + nStart = str.indexOf( "'" , nFound ); + nStop = str.indexOf( "'" , nStart +1 ); + } + else + { + int nStop = str.indexOf( "\"" , nStart +1); + } + + if( nStart >= 0 && nStop >= 0 && nStart+1 < nStop ) + { + // remove encoding tag from file + memmove( &( seq.getArray()[nFound] ) , + &( seq.getArray()[nStop+1]) , + seq.getLength() - nStop -1); + seq.realloc( seq.getLength() - ( nStop+1 - nFound ) ); +// str = String( (char * ) seq.getArray() , seq.getLen() ); + } + } + } +} + +// Checks, if enough data has been accumulated to recognize the encoding +sal_Bool XMLFile2UTFConverter::isEncodingRecognizable( const Sequence< sal_Int8 > &seq) +{ + const sal_Int8 *pSource = seq.getConstArray(); + sal_Bool bCheckIfFirstClosingBracketExsists = sal_False; + + if( seq.getLength() < 8 ) { + // no recognition possible, when less than 8 bytes are available + return sal_False; + } + + if( ! strncmp( (const char * ) pSource , "<?xml" , 4 ) ) { + // scan if the <?xml tag finishes within this buffer + bCheckIfFirstClosingBracketExsists = sal_True; + } + else if( ('<' == pSource[0] || '<' == pSource[2] ) && + ( ('?' == pSource[4] || '?' == pSource[6] ) ) ) + { + // check for utf-16 + bCheckIfFirstClosingBracketExsists = sal_True; + } + else if( ( '<' == pSource[1] || '<' == pSource[3] ) && + ( '?' == pSource[5] || '?' == pSource[7] ) ) + { + // check for + bCheckIfFirstClosingBracketExsists = sal_True; + } + + if( bCheckIfFirstClosingBracketExsists ) + { + for( sal_Int32 i = 0; i < seq.getLength() ; i ++ ) + { + // whole <?xml tag is valid + if( '>' == pSource[ i ] ) + { + return sal_True; + } + } + return sal_False; + } + + // No <? tag in front, no need for a bigger buffer + return sal_True; +} + +sal_Bool XMLFile2UTFConverter::scanForEncoding( Sequence< sal_Int8 > &seq ) +{ + const sal_Int8 *pSource = seq.getConstArray(); + sal_Bool bReturn = sal_True; + + if( seq.getLength() < 4 ) { + // no recognition possible, when less than 4 bytes are available + return sal_False; + } + + // first level : detect possible file formats + if( ! strncmp( (const char * ) pSource , "<?xml" , 4 ) ) { + + // scan for encoding + OString str( (const sal_Char *) pSource , seq.getLength() ); + + // cut sequence to first line break + //find first line break; + int nMax = str.indexOf( 10 ); + if( nMax >= 0 ) + { + str = str.copy( 0 , nMax ); + } + + int nFound = str.indexOf( " encoding" ); + if( nFound < str.getLength() ) { + int nStop; + int nStart = str.indexOf( "\"" , nFound ); + if( nStart < 0 || str.indexOf( "'" , nFound ) < nStart ) + { + nStart = str.indexOf( "'" , nFound ); + nStop = str.indexOf( "'" , nStart +1 ); + } + else + { + int nStop = str.indexOf( "\"" , nStart +1); + } + if( nStart >= 0 && nStop >= 0 && nStart+1 < nStop ) + { + // encoding found finally + m_sEncoding = str.copy( nStart+1 , nStop - nStart - 1 ); + } + } + } + else if( 0xFE == pSource[0] && 0xFF == pSource[1] ) { + // UTF-16 big endian + // conversion is done so that encoding information can be easily extracted + m_sEncoding = "utf-16"; + } + else if( 0xFF == pSource[0] && 0xFE == pSource[1] ) { + // UTF-16 little endian + // conversion is done so that encoding information can be easily extracted + m_sEncoding = "utf-16"; + } + else if( 0x00 == pSource[0] && 0x3c == pSource[1] && 0x00 == pSource[2] && 0x3f == pSource[3] ) { + // UTF-16 big endian without byte order mark (this is (strictly speaking) an error.) + // The byte order mark is simply added + + // simply add the byte order mark ! + seq.realloc( seq.getLength() + 2 ); + memmove( &( seq.getArray()[2] ) , seq.getArray() , seq.getLength() ); + ((sal_uInt8*)seq.getArray())[0] = 0xFE; + ((sal_uInt8*)seq.getArray())[1] = 0xFF; + + m_sEncoding = "utf-16"; + } + else if( 0x3c == pSource[0] && 0x00 == pSource[1] && 0x3f == pSource[2] && 0x00 == pSource[3] ) { + // UTF-16 little endian without byte order mark (this is (strictly speaking) an error.) + // The byte order mark is simply added + + seq.realloc( seq.getLength() + 2 ); + memmove( &( seq.getArray()[2] ) , seq.getArray() , seq.getLength() ); + ((sal_uInt8*)seq.getArray())[0] = 0xFF; + ((sal_uInt8*)seq.getArray())[1] = 0xFE; + + m_sEncoding = "utf-16"; + } + else if( 0x00 == pSource[0] && 0x00 == pSource[1] && 0x00 == pSource[2] && 0x3c == pSource[3] ) { + // UCS-4 big endian + m_sEncoding = "ucs-4"; + } + else if( 0x3c == pSource[0] && 0x00 == pSource[1] && 0x00 == pSource[2] && 0x00 == pSource[3] ) { + // UCS-4 little endian + m_sEncoding = "ucs-4"; + } + else if( 0x4c == pSource[0] && 0x6f == pSource[1] && 0xa7 == pSource[2] && 0x94 == pSource[3] ) { + // EBCDIC + bReturn = sal_False; // must be extended + } + else { + // other + // UTF8 is directly recognized by the parser. + bReturn = sal_False; + } + + return bReturn; +} + +void XMLFile2UTFConverter::initializeDecoding() +{ + + if( m_sEncoding.getLength() ) + { + rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( m_sEncoding.getStr() ); + if( encoding != RTL_TEXTENCODING_UTF8 ) + { + m_pText2Unicode = new Text2UnicodeConverter( m_sEncoding ); + m_pUnicode2Text = new Unicode2TextConverter( RTL_TEXTENCODING_UTF8 ); + } + } +} + + +//---------------------------------------------- +// +// Text2UnicodeConverter +// +//---------------------------------------------- +Text2UnicodeConverter::Text2UnicodeConverter( const OString &sEncoding ) +{ + rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( sEncoding.getStr() ); + if( RTL_TEXTENCODING_DONTKNOW == encoding ) + { + m_bCanContinue = sal_False; + m_bInitialized = sal_False; + } + else + { + init( encoding ); + } +} + +Text2UnicodeConverter::Text2UnicodeConverter( rtl_TextEncoding encoding ) +{ + init( encoding ); +} + + +Text2UnicodeConverter::~Text2UnicodeConverter() +{ + if( m_bInitialized ) + { + rtl_destroyTextToUnicodeContext( m_convText2Unicode , m_contextText2Unicode ); + rtl_destroyUnicodeToTextConverter( m_convText2Unicode ); + } +} + +void Text2UnicodeConverter::init( rtl_TextEncoding encoding ) +{ + m_bCanContinue = sal_True; + m_bInitialized = sal_True; + + m_convText2Unicode = rtl_createTextToUnicodeConverter(encoding); + m_contextText2Unicode = rtl_createTextToUnicodeContext( m_convText2Unicode ); + m_rtlEncoding = encoding; +} + + +Sequence<sal_Unicode> Text2UnicodeConverter::convert( const Sequence<sal_Int8> &seqText ) +{ + sal_uInt32 uiInfo; + sal_Size nSrcCvtBytes = 0; + sal_Size nTargetCount = 0; + sal_Size nSourceCount = 0; + + // the whole source size + sal_Int32 nSourceSize = seqText.getLength() + m_seqSource.getLength(); + Sequence<sal_Unicode> seqUnicode ( nSourceSize ); + + const sal_Int8 *pbSource = seqText.getConstArray(); + sal_Int8 *pbTempMem = 0; + + if( m_seqSource.getLength() ) { + // put old rest and new byte sequence into one array + pbTempMem = new sal_Int8[ nSourceSize ]; + memcpy( pbTempMem , m_seqSource.getConstArray() , m_seqSource.getLength() ); + memcpy( &(pbTempMem[ m_seqSource.getLength() ]) , seqText.getConstArray() , seqText.getLength() ); + pbSource = pbTempMem; + + // set to zero again + m_seqSource = Sequence< sal_Int8 >(); + } + + while( sal_True ) { + + /* All invalid characters are transformed to the unicode undefined char */ + nTargetCount += rtl_convertTextToUnicode( + m_convText2Unicode, + m_contextText2Unicode, + ( const sal_Char * ) &( pbSource[nSourceCount] ), + nSourceSize - nSourceCount , + &( seqUnicode.getArray()[ nTargetCount ] ), + seqUnicode.getLength() - nTargetCount, + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT | + RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT, + &uiInfo, + &nSrcCvtBytes ); + nSourceCount += nSrcCvtBytes; + + if( uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL ) { + // save necessary bytes for next conversion + seqUnicode.realloc( seqUnicode.getLength() * 2 ); + continue; + } + break; + } + if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL ) { + m_seqSource.realloc( nSourceSize - nSourceCount ); + memcpy( m_seqSource.getArray() , &(pbSource[nSourceCount]) , nSourceSize-nSourceCount ); + } + + + if( pbTempMem ) { + delete pbTempMem; + } + + // set to correct unicode size + seqUnicode.realloc( nTargetCount ); + + return seqUnicode; +} + + + +//---------------------------------------------- +// +// Unicode2TextConverter +// +//---------------------------------------------- +Unicode2TextConverter::Unicode2TextConverter( const OString &sEncoding ) +{ + rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( sEncoding.getStr() ); + if( RTL_TEXTENCODING_DONTKNOW == encoding ) { + m_bCanContinue = sal_False; + m_bInitialized = sal_False; + } + else { + init( encoding ); + } + +} + +Unicode2TextConverter::Unicode2TextConverter( rtl_TextEncoding encoding ) +{ + init( encoding ); +} + + +Unicode2TextConverter::~Unicode2TextConverter() +{ + if( m_bInitialized ) { + rtl_destroyUnicodeToTextContext( m_convUnicode2Text , m_contextUnicode2Text ); + rtl_destroyUnicodeToTextConverter( m_convUnicode2Text ); + } +} + + +Sequence<sal_Int8> Unicode2TextConverter::convert(const sal_Unicode *puSource , sal_Int32 nSourceSize) +{ + sal_Unicode *puTempMem = 0; + + if( m_seqSource.getLength() ) { + // For surrogates ! + // put old rest and new byte sequence into one array + // In general when surrogates are used, they should be rarely + // cut off between two convert()-calls. So this code is used + // rarely and the extra copy is acceptable. + nSourceSize += m_seqSource.getLength(); + + puTempMem = new sal_Unicode[ nSourceSize ]; + memcpy( puTempMem , + m_seqSource.getConstArray() , + m_seqSource.getLength() * sizeof( sal_Unicode ) ); + memcpy( + &(puTempMem[ m_seqSource.getLength() ]) , + puSource , + nSourceSize*sizeof( sal_Unicode ) ); + puSource = puTempMem; + + m_seqSource = Sequence< sal_Unicode > (); + } + + + sal_Size nTargetCount = 0; + sal_Size nSourceCount = 0; + + sal_uInt32 uiInfo; + sal_Size nSrcCvtChars; + + // take nSourceSize * 3 as preference + // this is an upper boundary for converting to utf8, + // which most often used as the target. + sal_Int32 nSeqSize = nSourceSize * 3; + + Sequence<sal_Int8> seqText( nSeqSize ); + sal_Char *pTarget = (sal_Char *) seqText.getArray(); + while( sal_True ) { + + nTargetCount += rtl_convertUnicodeToText( + m_convUnicode2Text, + m_contextUnicode2Text, + &( puSource[nSourceCount] ), + nSourceSize - nSourceCount , + &( pTarget[nTargetCount] ), + nSeqSize - nTargetCount, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT | + RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT , + &uiInfo, + &nSrcCvtChars); + nSourceCount += nSrcCvtChars; + + if( uiInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) { + nSeqSize = nSeqSize *2; + seqText.realloc( nSeqSize ); // double array size + pTarget = ( sal_Char * ) seqText.getArray(); + continue; + } + break; + } + + // for surrogates + if( uiInfo & RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL ) { + m_seqSource.realloc( nSourceSize - nSourceCount ); + memcpy( m_seqSource.getArray() , + &(puSource[nSourceCount]), + (nSourceSize - nSourceCount) * sizeof( sal_Unicode ) ); + } + + if( puTempMem ) { + delete puTempMem; + } + + // reduce the size of the buffer (fast, no copy necessary) + seqText.realloc( nTargetCount ); + + return seqText; +} + +void Unicode2TextConverter::init( rtl_TextEncoding encoding ) +{ + m_bCanContinue = sal_True; + m_bInitialized = sal_True; + + m_convUnicode2Text = rtl_createUnicodeToTextConverter( encoding ); + m_contextUnicode2Text = rtl_createUnicodeToTextContext( m_convUnicode2Text ); + m_rtlEncoding = encoding; +}; + + diff --git a/sax/test/makefile.mk b/sax/test/makefile.mk new file mode 100644 index 000000000000..451e999f01ea --- /dev/null +++ b/sax/test/makefile.mk @@ -0,0 +1,101 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ +# +# 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): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=.. + +PRJNAME=extensions +TARGET=workben +LIBTARGET=NO + +TARGETTYPE=CUI +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk +# --- Files -------------------------------------------------------- + + + +# +# std testcomponent +# +APP1TARGET = testcomponent +APP2TARGET = saxdemo + +APP1OBJS = $(OBJ)$/testcomponent.obj +APP1STDLIBS = $(SALLIB) \ + $(CPPULIB)\ + $(CPPUHELPERLIB) + + +APP2OBJS = $(OBJ)$/saxdemo.obj +APP2STDLIBS = $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/sax/test/sax/exports.dxp b/sax/test/sax/exports.dxp new file mode 100644 index 000000000000..ce95ae0f8deb --- /dev/null +++ b/sax/test/sax/exports.dxp @@ -0,0 +1,3 @@ +component_getImplementationEnvironment +component_getFactory +component_writeInfo
\ No newline at end of file diff --git a/sax/test/sax/factory.hxx b/sax/test/sax/factory.hxx new file mode 100644 index 000000000000..a4fea3a5c20b --- /dev/null +++ b/sax/test/sax/factory.hxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * $RCSfile: factory.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <rtl/strbuf.hxx> + +Reference< XInterface > SAL_CALL OSaxWriterTest_CreateInstance( + const Reference< XMultiServiceFactory > & rSMgr ) throw ( Exception ); +OUString OSaxWriterTest_getServiceName( ) throw(); +OUString OSaxWriterTest_getImplementationName( ) throw(); +Sequence<OUString> OSaxWriterTest_getSupportedServiceNames( ) throw(); + +#define BUILD_ERROR(expr, Message)\ + {\ + m_seqErrors.realloc( m_seqErrors.getLength() + 1 ); \ + m_seqExceptions.realloc( m_seqExceptions.getLength() + 1 ); \ + OStringBuffer str(128); \ + str.append( __FILE__ );\ + str.append( " " ); \ + str.append( "(" ); \ + str.append( OString::valueOf( (sal_Int32)__LINE__) );\ + str.append(")\n" );\ + str.append( "[ " ); \ + str.append( #expr ); \ + str.append( " ] : " ); \ + str.append( Message ); \ + m_seqErrors.getArray()[ m_seqErrors.getLength()-1] =\ + OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \ + }\ + ((void)0) + + +#define WARNING_ASSERT(expr, Message) \ + if( ! (expr) ) { \ + m_seqWarnings.realloc( m_seqErrors.getLength() +1 ); \ + OStringBuffer str(128);\ + str.append( __FILE__);\ + str.append( " "); \ + str.append( "(" ); \ + str.append(OString::valueOf( (sal_Int32)__LINE__)) ;\ + str.append( ")\n");\ + str.append( "[ " ); \ + str.append( #expr ); \ + str.append( " ] : ") ; \ + str.append( Message); \ + m_seqWarnings.getArray()[ m_seqWarnings.getLength()-1] =\ + OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \ + return; \ + }\ + ((void)0) + +#define ERROR_ASSERT(expr, Message) \ + if( ! (expr) ) { \ + BUILD_ERROR(expr, Message );\ + return; \ + }\ + ((void)0) + +#define ERROR_EXCEPTION_ASSERT(expr, Message, Exception) \ + if( !(expr)) { \ + BUILD_ERROR(expr,Message);\ + m_seqExceptions.getArray()[ m_seqExceptions.getLength()-1] = Any( Exception );\ + return; \ + } \ + ((void)0) + diff --git a/sax/test/sax/makefile.mk b/sax/test/sax/makefile.mk new file mode 100644 index 000000000000..062b3073243d --- /dev/null +++ b/sax/test/sax/makefile.mk @@ -0,0 +1,99 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ +# +# 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): _______________________________________ +# +# +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=extensions +TARGET=testsax +USE_DEFFILE=TRUE +ENABLE_EXCEPTIONS=TRUE +# --- Settings ----------------------------------------------------- +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + + +SLOFILES = $(SLO)$/testsax.obj \ + $(SLO)$/testwriter.obj + + +SHL1TARGET= $(TARGET) +SHL1IMPLIB= i$(TARGET) + +SHL1STDLIBS= \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) + + +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEPN= makefile.mk $(SHL1LIBS) +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) +DEF1EXPORTFILE= exports.dxp + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/sax/test/sax/testsax.cxx b/sax/test/sax/testsax.cxx new file mode 100644 index 000000000000..6de45e7acf38 --- /dev/null +++ b/sax/test/sax/testsax.cxx @@ -0,0 +1,902 @@ +/************************************************************************* + * + * $RCSfile: testsax.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <stdio.h> +#include <string.h> +#include <assert.h> + +#include <osl/time.h> +#include <osl/diagnose.h> + + +#include <com/sun/star/test/XSimpleTest.hpp> + +#include <com/sun/star/io/XOutputStream.hpp> + +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase3.hxx> + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::test; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::xml::sax; + +#include "factory.hxx" + +/**** +* test szenarios : +* +* +* +****/ + +class OSaxParserTest : public WeakImplHelper1< XSimpleTest > +{ +public: + OSaxParserTest( const Reference < XMultiServiceFactory > & rFactory ) : m_rFactory( rFactory ) + { + } +public: + virtual void SAL_CALL testInvariant( + const OUString& TestName, + const Reference < XInterface >& TestObject) + throw ( IllegalArgumentException, RuntimeException); + + virtual sal_Int32 SAL_CALL test( + const OUString& TestName, + const Reference < XInterface >& TestObject, + sal_Int32 hTestHandle) + throw ( IllegalArgumentException,RuntimeException); + + virtual sal_Bool SAL_CALL testPassed(void) throw ( RuntimeException); + virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException); + virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException); + +private: + void testSimple( const Reference < XParser > &r ); + void testNamespaces( const Reference < XParser > &r ); + void testFile( const Reference < XParser > &r ); + void testEncoding( const Reference < XParser > &rParser ); + void testPerformance( const Reference < XParser > &rParser ); + +private: + Sequence<Any> m_seqExceptions; + Sequence<OUString> m_seqErrors; + Sequence<OUString> m_seqWarnings; + Reference < XMultiServiceFactory > m_rFactory; +}; + + + +/** +* for external binding +* +* +**/ +Reference < XInterface > SAL_CALL OSaxParserTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw(Exception) +{ + OSaxParserTest *p = new OSaxParserTest( rSMgr ); + return Reference < XInterface > ( SAL_STATIC_CAST( OWeakObject * , p ) ); +} + + +OUString OSaxParserTest_getServiceName( ) throw () +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("test.com.sun.star.xml.sax.Parser" )); +} + +OUString OSaxParserTest_getImplementationName( ) throw () +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("test.extensions.xml.sax.Parser")); +} + +Sequence<OUString> OSaxParserTest_getSupportedServiceNames( ) throw () +{ + Sequence<OUString> aRet(1); + + aRet.getArray()[0] = OSaxParserTest_getImplementationName( ); + + return aRet; +} + + + + +void OSaxParserTest::testInvariant( + const OUString& TestName, + const Reference < XInterface >& TestObject ) + throw ( IllegalArgumentException, RuntimeException) +{ + if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) == TestName ) { + Reference < XParser > parser( TestObject , UNO_QUERY ); + + ERROR_ASSERT( parser.is() , "XDataInputStream cannot be queried" ); + } +} + + +sal_Int32 OSaxParserTest::test( + const OUString& TestName, + const Reference < XInterface >& TestObject, + sal_Int32 hTestHandle) + throw ( IllegalArgumentException, RuntimeException) +{ + if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) == TestName ) { + try + { + if( 0 == hTestHandle ) { + testInvariant( TestName , TestObject ); + } + else { + + Reference < XParser > parser( TestObject , UNO_QUERY ); + + if( 1 == hTestHandle ) { + testSimple( parser ); + } + else if( 2 == hTestHandle ) { + testNamespaces( parser ); + } + else if( 3 == hTestHandle ) { + testEncoding( parser ); + } + else if( 4 == hTestHandle ) { + testFile( parser ); + } + else if( 5 == hTestHandle ) { + testPerformance( parser ); + } + } + } + catch( Exception & e ) + { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US); + BUILD_ERROR( 0 , o.getStr() ); + } + catch( ... ) + { + BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" ); + } + + hTestHandle ++; + + if( hTestHandle >= 6) { + // all tests finished. + hTestHandle = -1; + } + } + else { + BUILD_ERROR( 0 , "service not supported by test." ); + } + return hTestHandle; +} + + + +sal_Bool OSaxParserTest::testPassed(void) throw (RuntimeException) +{ + return m_seqErrors.getLength() == 0; +} + + +Sequence< OUString > OSaxParserTest::getErrors(void) throw (RuntimeException) +{ + return m_seqErrors; +} + + +Sequence< Any > OSaxParserTest::getErrorExceptions(void) throw (RuntimeException) +{ + return m_seqExceptions; +} + + +Sequence< OUString > OSaxParserTest::getWarnings(void) throw (RuntimeException) +{ + return m_seqWarnings; +} + +Reference < XInputStream > createStreamFromSequence( + const Sequence<sal_Int8> seqBytes , + const Reference < XMultiServiceFactory > &xSMgr ) +{ + Reference < XInterface > xOutStreamService = + xSMgr->createInstance( L"com.sun.star.io.Pipe" ); + assert( xOutStreamService.is() ); + Reference< XOutputStream > rOutStream( xOutStreamService , UNO_QUERY ); + assert( rOutStream.is() ); + + Reference< XInputStream > rInStream( xOutStreamService , UNO_QUERY ); + assert( rInStream.is() ); + + rOutStream->writeBytes( seqBytes ); + rOutStream->flush(); + rOutStream->closeOutput(); + + return rInStream; +} + +Reference< XInputStream > createStreamFromFile( + const char *pcFile , + const Reference < XMultiServiceFactory > &xSMgr ) +{ + FILE *f = fopen( pcFile , "rb" ); + Reference< XInputStream > r; + + if( f ) { + fseek( f , 0 , SEEK_END ); + int nLength = ftell( f ); + fseek( f , 0 , SEEK_SET ); + + Sequence<sal_Int8> seqIn(nLength); + fread( seqIn.getArray() , nLength , 1 , f ); + + r = createStreamFromSequence( seqIn , xSMgr ); + fclose( f ); + } + return r; +} + + + + + + + + + +// #define PCHAR_TO_OUSTRING(x) OStringToOUString(x,CHARSET_PC_1252) +// #define USTRING_TO_PCHAR(x) UStringToString(x,CHARSET_PC_437).GetStr() + + + +class TestDocumentHandler : + public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler > +{ +public: + TestDocumentHandler( const Reference < XMultiServiceFactory > &r , sal_Bool bPrint ) + { + m_xSMgr = r; + m_bPrint = bPrint; + } + +public: // Error handler + virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Error !\n" ); + throw SAXException( + OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) , + Reference < XInterface >() , + aSAXParseException ); + } + virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Fatal Error !\n" ); + } + virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Warning !\n" ); + } + + +public: // ExtendedDocumentHandler + + virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException) + { + m_iLevel = 0; + m_iElementCount = 0; + m_iAttributeCount = 0; + m_iWhitespaceCount =0; + m_iCharCount=0; + if( m_bPrint ) { + printf( "document started\n" ); + } + } + virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException) + { + if( m_bPrint ) { + printf( "document finished\n" ); + printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n", + m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount ); + } + } + virtual void SAL_CALL startElement(const OUString& aName, + const Reference< XAttributeList > & xAttribs) + throw (SAXException,RuntimeException) + { + + if( m_rLocator.is() ) { + if( m_bPrint ) + { + OString o = OUStringToOString( m_rLocator->getSystemId() , RTL_TEXTENCODING_UTF8 ); + printf( "%s(%d):" , o.getStr() , m_rLocator->getLineNumber() ); + } + } + if( m_bPrint ) { + int i; + for( i = 0; i < m_iLevel ; i ++ ) { + printf( " " ); + } + OString o = OUStringToOString(aName , RTL_TEXTENCODING_UTF8 ); + printf( "<%s> " , aName.getStr() ); + + for( i = 0 ; i < xAttribs->getLength() ; i ++ ) + { + OString o1 = OUStringToOString(xAttribs->getNameByIndex( i ), RTL_TEXTENCODING_UTF8 ); + OString o2 = OUStringToOString(xAttribs->getTypeByIndex( i ), RTL_TEXTENCODING_UTF8 ); + OString o3 = OUStringToOString(xAttribs->getValueByIndex( i ) , RTL_TEXTENCODING_UTF8 ); + printf( "(%s,%s,'%s')" , o1.getStr(), o2.getStr(), o3.getStr() ); + } + printf( "\n" ); + } + m_iLevel ++; + m_iElementCount ++; + m_iAttributeCount += xAttribs->getLength(); + } + + virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException) + { + assert( m_iLevel ); + m_iLevel --; + if( m_bPrint ) { + int i; + for( i = 0; i < m_iLevel ; i ++ ) { + printf( " " ); + } + OString o = OUStringToOString(aName , RTL_TEXTENCODING_UTF8 ); + printf( "</%s>\n" , o.getStr() ); + } + } + + virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException) + { + if( m_bPrint ) { + int i; + for( i = 0; i < m_iLevel ; i ++ ) { + printf( " " ); + } + OString o = OUStringToOString(aChars , RTL_TEXTENCODING_UTF8 ); + printf( "%s\n" , o.getStr() ); + } + m_iCharCount += aChars.len(); + } + virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException) + { + m_iWhitespaceCount += aWhitespaces.len(); + } + + virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException) + { + if( m_bPrint ) + { + OString o1 = OUStringToOString(aTarget, RTL_TEXTENCODING_UTF8 ); + OString o2 = OUStringToOString(aData, RTL_TEXTENCODING_UTF8 ); + printf( "PI : %s,%s\n" , o1.getStr() , o2.getStr() ); + } + } + + virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator) + throw (SAXException,RuntimeException) + { + m_rLocator = xLocator; + } + + virtual InputSource SAL_CALL resolveEntity( + const OUString& sPublicId, + const OUString& sSystemId) + throw (SAXException,RuntimeException) + { + InputSource source; + source.sSystemId = sSystemId; + source.sPublicId = sPublicId; + + source.aInputStream = createStreamFromFile( + OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) , m_xSMgr ); + + return source; + } + + virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException) + { + if( m_bPrint ) { + printf( "CDataStart :\n" ); + } + } + virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException) + { + if( m_bPrint ) { + printf( "CEndStart :\n" ); + } + } + virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException) + { + if( m_bPrint ) { + OString o1 = OUStringToOString(sComment, RTL_TEXTENCODING_UTF8 ); + printf( "<!--%s-->\n" , o1.getStr() ); + } + } + virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException) + { + if( m_bPrint ) + { + OString o1 = OUStringToOString(sString, RTL_TEXTENCODING_UTF8 ); + printf( "UNKNOWN : {%s}\n" , o1.getStr() ); + } + } + + virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException ) + { + + } + + +public: + int m_iLevel; + int m_iElementCount; + int m_iAttributeCount; + int m_iWhitespaceCount; + int m_iCharCount; + sal_Bool m_bPrint; + + Reference < XMultiServiceFactory > m_xSMgr; + Reference < XLocator > m_rLocator; +}; + + +void OSaxParserTest::testSimple( const Reference < XParser > &rParser ) +{ + + char TestString[] = "<!DOCTYPE personnel [\n" + "<!ENTITY testInternal \"internal Test!\">\n" + "<!ENTITY test SYSTEM \"external_entity.xml\">\n" + "]>\n" + "<personnel>\n" + "<person> fjklsfdklsdfkl\n" + "fjklsfdklsdfkl\n" + "<?testpi pidata?>\n" + "&testInternal;\n" + "<HUHU x='5' y='kjfd'> blahuhu\n" + "<HI> blahi\n" + " <![CDATA[<greeting>Hello, '+1+12world!</greeting>]]>\n" + " <!-- huhu <jdk> -->\n" + "<?testpi pidata?>\n" + "</HI>\n" + "aus XMLTest\n" + "</HUHU>\n" + "</person>\n" + "</personnel>\n\n\n"; + + Sequence< sal_Int8> seqBytes( strlen( TestString ) ); + memcpy( seqBytes.getArray() , TestString , strlen( TestString ) ); + + + Reference< XInputStream > rInStream; + OUString sInput; + rInStream = createStreamFromSequence( seqBytes , m_rFactory ); + sInput = OUString( OUString( RTL_CONSTASCII_USTRINGPARAM("internal")) ); + + if( rParser.is() ) { + InputSource source; + + source.aInputStream = rInStream; + source.sSystemId = sInput; + + TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False ); + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY ); + Reference< XEntityResolver > + rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + + try + { + rParser->parseStream( source ); + ERROR_ASSERT( pDocHandler->m_iElementCount == 4 , "wrong element count" ); + ERROR_ASSERT( pDocHandler->m_iAttributeCount == 2 , "wrong attribut count" ); + ERROR_ASSERT( pDocHandler->m_iCharCount == 130 , "wrong char count" ); + ERROR_ASSERT( pDocHandler->m_iWhitespaceCount == 0, "wrong whitespace count" ); + } + catch( SAXParseException & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + } + catch( SAXException & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + } + catch( Exception & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + } + catch( ... ) + { + BUILD_ERROR( 1 , "unknown exception" ); + } + } +} + +void OSaxParserTest::testNamespaces( const Reference < XParser > &rParser ) +{ + + char TestString[] = + "<?xml version='1.0'?>\n" + "<!-- all elements here are explicitly in the HTML namespace -->\n" + "<html:html xmlns:html='http://www.w3.org/TR/REC-html40'>\n" + "<html:head><html:title>Frobnostication</html:title></html:head>\n" + "<html:body><html:p>Moved to \n" + "<html:a href='http://frob.com'>here.</html:a></html:p></html:body>\n" + "</html:html>\n"; + + Sequence<sal_Int8> seqBytes( strlen( TestString ) ); + memcpy( seqBytes.getArray() , TestString , strlen( TestString ) ); + + + Reference< XInputStream > rInStream; + OUString sInput; + + rInStream = createStreamFromSequence( seqBytes , m_rFactory ); + sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "internal" )); + + if( rParser.is() ) { + InputSource source; + + source.aInputStream = rInStream; + source.sSystemId = sInput; + + TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False ); + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY ); + Reference< XEntityResolver > rEntityResolver( + (XEntityResolver *) pDocHandler , UNO_QUERY ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + + try + { + rParser->parseStream( source ); + ERROR_ASSERT( pDocHandler->m_iElementCount == 6 , "wrong element count" ); + ERROR_ASSERT( pDocHandler->m_iAttributeCount == 2 , "wrong attribut count" ); + ERROR_ASSERT( pDocHandler->m_iCharCount == 33, "wrong char count" ); + ERROR_ASSERT( pDocHandler->m_iWhitespaceCount == 0 , "wrong whitespace count" ); + } + catch( Exception & e ) { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + } + catch( ... ) + { + BUILD_ERROR( 1 , "unknown exception" ); + } + } +} + +void OSaxParserTest::testEncoding( const Reference < XParser > &rParser ) +{ + char TestString[] = + "<?xml version='1.0' encoding=\"iso-8859-1\"?>\n" + "<!-- all elements here are explicitly in the HTML namespace -->\n" + "<html:html xmlns:html='http://www.w3.org/TR/REC-html40'>\n" + "<html:head><html:title>Frobnostication</html:title></html:head>\n" + "<html:body><html:p>Moved to \n" + "<html:a href='http://frob.com'>here.</html:a></html:p></html:body>\n" + "</html:html>\n"; + + Sequence<sal_Int8> seqBytes( strlen( TestString ) ); + memcpy( seqBytes.getArray() , TestString , strlen( TestString ) ); + + + Reference< XInputStream > rInStream; + OUString sInput; + + rInStream = createStreamFromSequence( seqBytes , m_rFactory ); + sInput = OUString( RTL_CONSTASCII_USTRINGPARAM("internal") ); + + if( rParser.is() ) { + InputSource source; + + source.aInputStream = rInStream; + source.sSystemId = sInput; + + TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False ); + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY ); + Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + try + { + rParser->parseStream( source ); + } + catch( Exception & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + } + catch ( ... ) + { + BUILD_ERROR( 1 , "unknown exception" ); + } + } +} + +void OSaxParserTest::testFile( const Reference < XParser > & rParser ) +{ + + Reference< XInputStream > rInStream = createStreamFromFile( "testsax.xml" , m_rFactory ); + OUString sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "testsax.xml" ) ); + + + if( rParser.is() && rInStream.is() ) { + InputSource source; + + source.aInputStream = rInStream; + source.sSystemId = sInput; + + TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_True ); + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY ); + Reference < XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY ); + Reference < XErrorHandler > rErrorHandler( ( XErrorHandler * )pDocHandler , UNO_QUERY ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + rParser->setErrorHandler( rErrorHandler ); + + try + { + rParser->parseStream( source ); + } + catch( SAXParseException & e ) { + Any any; + any <<= e; + + while(sal_True) { + SAXParseException *pEx; + if( any.getValueType() == getCppuType( &e ) ) { + pEx = ( SAXParseException * ) any.getValue(); + OString o1 = OUStringToOString(pEx->Message, RTL_TEXTENCODING_UTF8 ); + printf( "%s\n" , o1.getStr() ); + any = pEx->WrappedException; + } + else { + break; + } + } + } + catch( SAXException & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + BUILD_ERROR( 1 , o1.getStr() ); + + } + catch( Exception & e ) { + printf( "normal exception ! %s\n", e.Message ); + } + catch ( ... ) + { + printf( "any exception !!!!\n" ); + } + } +} + +void OSaxParserTest::testPerformance( const Reference < XParser > & rParser ) +{ + + Reference < XInputStream > rInStream = + createStreamFromFile( "testPerformance.xml" , m_rFactory ); + OUString sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "testperformance.xml") ); + + if( rParser.is() && rInStream.is() ) { + InputSource source; + + source.aInputStream = rInStream; + source.sSystemId = sInput; + + TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False ); + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY ); + Reference < XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY ); + Reference < XErrorHandler > rErrorHandler( ( XErrorHandler * )pDocHandler , UNO_QUERY ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + rParser->setErrorHandler( rErrorHandler ); + + try + { + TimeValue aStartTime, aEndTime; + osl_getSystemTime( &aStartTime ); + rParser->parseStream( source ); + osl_getSystemTime( &aEndTime ); + + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + + printf( "Performance reading : %g s\n" , fEnd - fStart ); + + } + catch( SAXParseException &e ) { + Any any; + any <<= e; + while(sal_True) { + if( any.getValueType() == getCppuType( &e ) ) { + SAXParseException ex; + any >>= ex; + OString o = OUStringToOString( ex.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + any <<= ex.WrappedException; + } + else { + break; + } + } + } + catch( SAXException &e ) { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + + } + catch( ... ) + { + printf( "any exception !!!!\n" ); + } + } +} + + +extern "C" +{ + + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + + +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + Reference< XRegistryKey > xKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey ) ); + + OUString str = + OUString( L"/" ) + + OSaxParserTest_getImplementationName() + + OUString( L"/UNO/SERVICES" ); + Reference< XRegistryKey > xNewKey = xKey->createKey( str ); + xNewKey->createKey( OSaxParserTest_getServiceName() ); + + str = + OUString( L"/" ) + + OSaxWriterTest_getImplementationName() + + OUString( L"/UNO/SERVICES" ); + + xNewKey = xKey->createKey( str ); + xNewKey->createKey( OSaxWriterTest_getServiceName() ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSHURE( sal_False, "### InvalidRegistryException!" ); + } + } + + return sal_False; +} + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + void * pRet = 0; + + if (pServiceManager ) + { + Reference< XSingleServiceFactory > xRet; + Reference< XMultiServiceFactory > xSMgr = + reinterpret_cast< XMultiServiceFactory * > ( pServiceManager ); + + OUString aImplementationName = OUString::createFromAscii( pImplName ); + + + if (aImplementationName == OSaxWriterTest_getImplementationName() ) + { + xRet = createSingleFactory( xSMgr, aImplementationName, + OSaxWriterTest_CreateInstance, + OSaxWriterTest_getSupportedServiceNames() ); + } + else if (aImplementationName == OSaxParserTest_getImplementationName() ) + { + xRet = createSingleFactory( xSMgr, aImplementationName, + OSaxParserTest_CreateInstance, + OSaxParserTest_getSupportedServiceNames() ); + } + if (xRet.is()) + { + xRet->acquire(); + pRet = xRet.get(); + } + } + + return pRet; +} + +} + + diff --git a/sax/test/sax/testwriter.cxx b/sax/test/sax/testwriter.cxx new file mode 100644 index 000000000000..5f06cf602abe --- /dev/null +++ b/sax/test/sax/testwriter.cxx @@ -0,0 +1,714 @@ +/************************************************************************* + * + * $RCSfile: testwriter.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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 <vector> +#include <stdio.h> +#include <assert.h> + +#include <com/sun/star/test/XSimpleTest.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> // for the multiservice-factories + +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +#include <osl/time.h> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase3.hxx> + + +using namespace ::std; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::test; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::xml::sax; + +#include "factory.hxx" + +class OFileWriter : + public WeakImplHelper1< XOutputStream > +{ +public: + OFileWriter( char *pcFile ) { strcpy( m_pcFile , pcFile ); m_f = 0; } + + +public: + virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL flush(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL closeOutput(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); +private: + char m_pcFile[256]; + FILE *m_f; +}; + + +void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + if( ! m_f ) { + m_f = fopen( m_pcFile , "w" ); + } + + fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f ); + +} + + +void OFileWriter::flush(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + fflush( m_f ); +} + +void OFileWriter::closeOutput(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + fclose( m_f ); + m_f = 0; +} + + +class OSaxWriterTest : + public WeakImplHelper1< XSimpleTest > +{ +public: + OSaxWriterTest( const Reference < XMultiServiceFactory > & rFactory ) : m_rFactory( rFactory ) + { + + } + ~OSaxWriterTest() {} + + +public: + virtual void SAL_CALL testInvariant( + const OUString& TestName, + const Reference < XInterface >& TestObject) + throw ( IllegalArgumentException, + RuntimeException); + + virtual sal_Int32 SAL_CALL test( + const OUString& TestName, + const Reference < XInterface >& TestObject, + sal_Int32 hTestHandle) + throw ( IllegalArgumentException,RuntimeException); + + virtual sal_Bool SAL_CALL testPassed(void) + throw ( RuntimeException); + virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException); + virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException); + +private: + void testSimple( const Reference< XExtendedDocumentHandler > &r ); + void testExceptions( const Reference< XExtendedDocumentHandler > &r ); + void testDTD( const Reference< XExtendedDocumentHandler > &r ); + void testPerformance( const Reference< XExtendedDocumentHandler > &r ); + void writeParagraph( const Reference< XExtendedDocumentHandler > &r , const OUString & s); + +private: + Sequence<Any> m_seqExceptions; + Sequence<OUString> m_seqErrors; + Sequence<OUString> m_seqWarnings; + Reference < XMultiServiceFactory > m_rFactory; + +}; + + + +/*---------------------------------------- +* +* Attributlist implementation +* +*----------------------------------------*/ +struct AttributeListImpl_impl; +class AttributeListImpl : public WeakImplHelper1< XAttributeList > +{ +public: + AttributeListImpl(); + AttributeListImpl( const AttributeListImpl & ); + ~AttributeListImpl(); + +public: + virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException); + virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException); + virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException); + +public: + void addAttribute( const OUString &sName , + const OUString &sType , + const OUString &sValue ); + void clear(); + +private: + struct AttributeListImpl_impl *m_pImpl; +}; + + +struct TagAttribute +{ + TagAttribute(){} + TagAttribute( const OUString &sName, + const OUString &sType , + const OUString &sValue ) + { + this->sName = sName; + this->sType = sType; + this->sValue = sValue; + } + + OUString sName; + OUString sType; + OUString sValue; +}; + +struct AttributeListImpl_impl +{ + AttributeListImpl_impl() + { + // performance improvement during adding + vecAttribute.reserve(20); + } + vector<struct TagAttribute> vecAttribute; +}; + + + +sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException) +{ + return m_pImpl->vecAttribute.size(); +} + + +AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) +{ + m_pImpl = new AttributeListImpl_impl; + *m_pImpl = *(r.m_pImpl); +} + +OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sName; + } + return OUString(); +} + + +OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sType; + } + return OUString(); +} + +OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sValue; + } + return OUString(); + +} + +OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sType; + } + } + return OUString(); +} + +OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sValue; + } + } + return OUString(); +} + + + +AttributeListImpl::AttributeListImpl() +{ + m_pImpl = new AttributeListImpl_impl; +} + + + +AttributeListImpl::~AttributeListImpl() +{ + delete m_pImpl; +} + + +void AttributeListImpl::addAttribute( const OUString &sName , + const OUString &sType , + const OUString &sValue ) +{ + m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) ); +} + +void AttributeListImpl::clear() +{ + m_pImpl->vecAttribute.clear(); + +} + + + + + + + + + + + +/** +* for external binding +* +* +**/ +Reference < XInterface > SAL_CALL OSaxWriterTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw (Exception) +{ + OSaxWriterTest *p = new OSaxWriterTest( rSMgr ); + Reference < XInterface > xService = *p; + return xService; +} + +OUString OSaxWriterTest_getServiceName( ) throw () +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("test.com.sun.star.xml.sax.Writer")); +} + +OUString OSaxWriterTest_getImplementationName( ) throw () +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("test.extensions.xml.sax.Writer")); +} + +Sequence<OUString> OSaxWriterTest_getSupportedServiceNames( ) throw () +{ + Sequence<OUString> aRet(1); + + aRet.getArray()[0] = OSaxWriterTest_getImplementationName( ); + + return aRet; +} + + + +void OSaxWriterTest::testInvariant( const OUString& TestName, + const Reference < XInterface >& TestObject ) + throw ( IllegalArgumentException, RuntimeException) +{ + if( L"com.sun.star.xml.sax.Writer" == TestName ) { + Reference< XDocumentHandler > doc( TestObject , UNO_QUERY ); + Reference< XExtendedDocumentHandler > ext( TestObject , UNO_QUERY ); + Reference< XActiveDataSource > source( TestObject , UNO_QUERY ); + + ERROR_ASSERT( doc.is() , "XDocumentHandler cannot be queried" ); + ERROR_ASSERT( ext.is() , "XExtendedDocumentHandler cannot be queried" ); + ERROR_ASSERT( source.is() , "XActiveDataSource cannot be queried" ); + } + else { + BUILD_ERROR( 0 , "wrong test" ); + } +} + + +sal_Int32 OSaxWriterTest::test( + const OUString& TestName, + const Reference < XInterface >& TestObject, + sal_Int32 hTestHandle) + throw ( IllegalArgumentException,RuntimeException) +{ + if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer")) == TestName ) + { + try + { + if( 0 == hTestHandle ) + { + testInvariant( TestName , TestObject ); + } + else + { + Reference< XExtendedDocumentHandler > writer( TestObject , UNO_QUERY ); + + if( 1 == hTestHandle ) { + testSimple( writer ); + } + else if( 2 == hTestHandle ) { + testExceptions( writer ); + } + else if( 3 == hTestHandle ) { + testDTD( writer ); + } + else if( 4 == hTestHandle ) { + testPerformance( writer ); + } + } + } + catch( Exception & e ) { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + BUILD_ERROR( 0 , o.getStr() ); + } + catch( ... ) + { + BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" ); + } + + hTestHandle ++; + + if( hTestHandle >= 5) { + // all tests finished. + hTestHandle = -1; + } + } + else { + BUILD_ERROR( 0 , "service not supported by test." ); + } + return hTestHandle; +} + + + +sal_Bool OSaxWriterTest::testPassed(void) throw (RuntimeException) +{ + return m_seqErrors.getLength() == 0; +} + + +Sequence< OUString > OSaxWriterTest::getErrors(void) throw (RuntimeException) +{ + return m_seqErrors; +} + + +Sequence< Any > OSaxWriterTest::getErrorExceptions(void) throw (RuntimeException) +{ + return m_seqExceptions; +} + + +Sequence< OUString > OSaxWriterTest::getWarnings(void) throw (RuntimeException) +{ + return m_seqWarnings; +} + +void OSaxWriterTest::writeParagraph( + const Reference< XExtendedDocumentHandler > &r , + const OUString & s) +{ + int nMax = s.len(); + int nStart = 0; + + Sequence<sal_uInt16> seq( s.len() ); + memcpy( seq.getArray() , s.getStr() , s.len() * sizeof( sal_uInt16 ) ); + + for( int n = 1 ; n < nMax ; n++ ){ + if( 32 == seq.getArray()[n] ) { + r->allowLineBreak(); + r->characters( s.copy( nStart , n - nStart ) ); + nStart = n; + } + } + r->allowLineBreak(); + r->characters( s.copy( nStart , n - nStart ) ); +} + + + +void OSaxWriterTest::testSimple( const Reference< XExtendedDocumentHandler > &r ) +{ + OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( + "Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter " + "wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile " + "bis zum bitteren Ende schreibt." )); + + OFileWriter *pw = new OFileWriter("output.xml"); + AttributeListImpl *pList = new AttributeListImpl; + + Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); + Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY ); + + Reference< XActiveDataSource > source( r , UNO_QUERY ); + + ERROR_ASSERT( ref.is() , "no output stream" ); + ERROR_ASSERT( source.is() , "no active data source" ); + + source->setOutputStream( ref ); + + r->startDocument(); + + pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )), + OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("bla\n u")) ); + pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("blub")) ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList ); + r->ignorableWhitespace( OUString() ); + + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) ); + r->ignorableWhitespace( OUString() ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList ); + r->ignorableWhitespace( OUString() ); + + // the enpassant must be converted & -> & + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("ü")) ); + + // Test added for mib. Tests if errors during conversions occurs + r->ignorableWhitespace( OUString() ); + sal_Char array[256]; + for( sal_Int32 n = 32 ; n < 254 ; n ++ ) { + array[n-32] = n; + } + array[254-32] = 0; + r->characters( + OStringToOUString( array , RTL_TEXTENCODING_SYMBOL ) + ); + r->ignorableWhitespace( OUString() ); + + // '>' must not be converted + r->startCDATA(); + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(">fsfsdf<")) ); + r->endCDATA(); + r->ignorableWhitespace( OUString() ); + + writeParagraph( r , testParagraph ); + + + r->ignorableWhitespace( OUString() ); + r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("Dies ist ein Kommentar !")) ); + r->ignorableWhitespace( OUString() ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList ); + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) ); + + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) ); + r->ignorableWhitespace( OUString() ); + + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) ); + r->endDocument(); + +} + +void OSaxWriterTest::testExceptions( const Reference< XExtendedDocumentHandler > & r ) +{ + + OFileWriter *pw = new OFileWriter("output2.xml"); + AttributeListImpl *pList = new AttributeListImpl; + + Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); + Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY ); + + Reference< XActiveDataSource > source( r , UNO_QUERY ); + + ERROR_ASSERT( ref.is() , "no output stream" ); + ERROR_ASSERT( source.is() , "no active data source" ); + + source->setOutputStream( ref ); + + { // startDocument must be called before start element + sal_Bool bException = sal_True; + try + { + r->startElement( L"huhu" , rList ); + bException = sal_False; + } + catch( SAXException &e ) + { + + } + ERROR_ASSERT( bException , "expected exception not thrown !" ); + } + + r->startDocument(); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList ); + r->startCDATA(); + + { + sal_Bool bException = sal_True; + try{ + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList ); + bException = sal_False; + } + catch( SAXException &e ) { + + } + ERROR_ASSERT( bException , "expected exception not thrown !" ); + } + + r->endCDATA(); + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) ); + + r->endDocument(); +} + + +void OSaxWriterTest::testDTD(const Reference< XExtendedDocumentHandler > &r ) +{ + OFileWriter *pw = new OFileWriter("outputDTD.xml"); + AttributeListImpl *pList = new AttributeListImpl; + + Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); + Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY ); + + Reference< XActiveDataSource > source( r , UNO_QUERY ); + + ERROR_ASSERT( ref.is() , "no output stream" ); + ERROR_ASSERT( source.is() , "no active data source" ); + + source->setOutputStream( ref ); + + + r->startDocument(); + r->unknown( OUString( RTL_CONSTASCII_USTRINGPARAM("<!DOCTYPE iCalendar >\n")) ); + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList ); + + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) ); + r->endDocument(); +} + +void OSaxWriterTest::testPerformance(const Reference< XExtendedDocumentHandler > &r ) +{ + OFileWriter *pw = new OFileWriter("testPerformance.xml"); + AttributeListImpl *pList = new AttributeListImpl; + + OUString testParagraph = + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter " + "wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile " + "bis zum bitteren Ende schreibt." )); + + + Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); + Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY ); + + Reference< XActiveDataSource > source( r , UNO_QUERY ); + + ERROR_ASSERT( ref.is() , "no output stream" ); + ERROR_ASSERT( source.is() , "no active data source" ); + + source->setOutputStream( ref ); + + TimeValue aStartTime, aEndTime; + osl_getSystemTime( &aStartTime ); + + + r->startDocument(); + // just write a bunch of xml tags ! + // for performance testing + sal_Int32 i2; + for( i2 = 0 ; i2 < 15 ; i2 ++ ) + { + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag") ) + + OUString::valueOf( i2 ), rList ); + for( sal_Int32 i = 0 ; i < 450 ; i ++ ) + { + r->ignorableWhitespace( OUString()); + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList ); + r->characters( testParagraph ); + + r->ignorableWhitespace( OUString() ); + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) ); + } + } + for( i2 = 14 ; i2 >= 0 ; i2-- ) + { + r->ignorableWhitespace( OUString() ); + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag") ) + OUString::valueOf( i2 ) ); + } + + r->endDocument(); + + osl_getSystemTime( &aEndTime ); + + double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0); + double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0); + + printf( "Performance writing : %g s\n" , fEnd - fStart ); +} diff --git a/sax/test/saxdemo.cxx b/sax/test/saxdemo.cxx new file mode 100644 index 000000000000..f4c57425864c --- /dev/null +++ b/sax/test/saxdemo.cxx @@ -0,0 +1,693 @@ +/************************************************************************* + * + * $RCSfile: saxdemo.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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): _______________________________________ + * + * + ************************************************************************/ + +//------------------------------------------------------ +// testcomponent - Loads a service and its testcomponent from dlls performs a test. +// Expands the dll-names depending on the actual environment. +// Example : testcomponent stardiv.uno.io.Pipe stm +// +// Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe +// + +#include <stdio.h> +#include <vector> + +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase3.hxx> + +#include <vos/dynload.hxx> +#include <vos/diagnose.hxx> + +#include <assert.h> + + +using namespace ::rtl; +using namespace ::std; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::io; + + +/************ + * Sequence of bytes -> InputStream + ************/ +class OInputStream : public WeakImplHelper1 < XInputStream > +{ +public: + OInputStream( const Sequence< sal_Int8 >&seq ) : + m_seq( seq ), + nPos( 0 ) + {} + +public: + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) + { + nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ? + m_seq.getLength() - nPos : + nBytesToRead; + aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead ); + nPos += nBytesToRead; + return nBytesToRead; + } + virtual sal_Int32 SAL_CALL readSomeBytes( + ::com::sun::star::uno::Sequence< sal_Int8 >& aData, + sal_Int32 nMaxBytesToRead ) + throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) + { + return readBytes( aData, nMaxBytesToRead ); + } + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) + { + // not implemented + } + virtual sal_Int32 SAL_CALL available( ) + throw(NotConnectedException, IOException, RuntimeException) + { + return m_seq.getLength() - nPos; + } + virtual void SAL_CALL closeInput( ) + throw(NotConnectedException, IOException, RuntimeException) + { + // not needed + } + sal_Int32 nPos; + Sequence< sal_Int8> m_seq; +}; + +//------------------------------- +// Helper : create an input stream from a file +//------------------------------ +Reference< XInputStream > createStreamFromFile( + const char *pcFile ) +{ + FILE *f = fopen( pcFile , "rb" ); + Reference< XInputStream > r; + + if( f ) { + fseek( f , 0 , SEEK_END ); + int nLength = ftell( f ); + fseek( f , 0 , SEEK_SET ); + + Sequence<sal_Int8> seqIn(nLength); + fread( seqIn.getArray() , nLength , 1 , f ); + + r = Reference< XInputStream > ( new OInputStream( seqIn ) ); + fclose( f ); + } + return r; +} + +//----------------------------------------- +// The document handler, which is needed for the saxparser +// The Documenthandler for reading sax +//----------------------------------------- +class TestDocumentHandler : + public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler > +{ +public: + TestDocumentHandler( ) + { + } + +public: // Error handler + virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Error !\n" ); + throw SAXException( + OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) , + Reference < XInterface >() , + aSAXParseException ); + } + virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Fatal Error !\n" ); + } + virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException) + { + printf( "Warning !\n" ); + } + + +public: // ExtendedDocumentHandler + + virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException) + { + m_iElementCount = 0; + m_iAttributeCount = 0; + m_iWhitespaceCount =0; + m_iCharCount=0; + printf( "document started\n" ); + } + virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException) + { + printf( "document finished\n" ); + printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n", + m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount ); + + } + virtual void SAL_CALL startElement(const OUString& aName, + const Reference< XAttributeList > & xAttribs) + throw (SAXException,RuntimeException) + { + m_iElementCount ++; + m_iAttributeCount += xAttribs->getLength(); + } + + virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException) + { + // ignored + } + + virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException) + { + m_iCharCount += aChars.len(); + } + virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException) + { + m_iWhitespaceCount += aWhitespaces.len(); + } + + virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException) + { + // ignored + } + + virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator) + throw (SAXException,RuntimeException) + { + // ignored + } + + virtual InputSource SAL_CALL resolveEntity( + const OUString& sPublicId, + const OUString& sSystemId) + throw (SAXException,RuntimeException) + { + InputSource source; + source.sSystemId = sSystemId; + source.sPublicId = sPublicId; + + source.aInputStream = createStreamFromFile( + OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) ); + + return source; + } + + virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException) + { + } + virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException) + { + } + virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException) + { + } + virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException) + { + } + + virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException ) + { + + } + +public: + int m_iElementCount; + int m_iAttributeCount; + int m_iWhitespaceCount; + int m_iCharCount; +}; + +//-------------------------------------- +// helper implementation for writing +// implements an XAttributeList +//------------------------------------- +struct AttributeListImpl_impl; +class AttributeListImpl : public WeakImplHelper1< XAttributeList > +{ +public: + AttributeListImpl(); + AttributeListImpl( const AttributeListImpl & ); + ~AttributeListImpl(); + +public: + virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException); + virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException); + virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException); + virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException); + +public: + void addAttribute( const OUString &sName , + const OUString &sType , + const OUString &sValue ); + void clear(); + +private: + struct AttributeListImpl_impl *m_pImpl; +}; + + +struct TagAttribute +{ + TagAttribute(){} + TagAttribute( const OUString &sName, + const OUString &sType , + const OUString &sValue ) + { + this->sName = sName; + this->sType = sType; + this->sValue = sValue; + } + + OUString sName; + OUString sType; + OUString sValue; +}; + +struct AttributeListImpl_impl +{ + AttributeListImpl_impl() + { + // performance improvement during adding + vecAttribute.reserve(20); + } + vector<struct TagAttribute> vecAttribute; +}; + + + +sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException) +{ + return m_pImpl->vecAttribute.size(); +} + + +AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) +{ + m_pImpl = new AttributeListImpl_impl; + *m_pImpl = *(r.m_pImpl); +} + +OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sName; + } + return OUString(); +} + + +OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sType; + } + return OUString(); +} + +OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException) +{ + if( i < m_pImpl->vecAttribute.size() ) { + return m_pImpl->vecAttribute[i].sValue; + } + return OUString(); + +} + +OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sType; + } + } + return OUString(); +} + +OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException) +{ + vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); + + for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { + if( (*ii).sName == sName ) { + return (*ii).sValue; + } + } + return OUString(); +} + + + +AttributeListImpl::AttributeListImpl() +{ + m_pImpl = new AttributeListImpl_impl; +} + + + +AttributeListImpl::~AttributeListImpl() +{ + delete m_pImpl; +} + + +void AttributeListImpl::addAttribute( const OUString &sName , + const OUString &sType , + const OUString &sValue ) +{ + m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) ); +} + +void AttributeListImpl::clear() +{ + m_pImpl->vecAttribute.clear(); +} + + +//-------------------------------------- +// helper function for writing +// ensures that linebreaks are inserted +// when writing a long text. +// Note: this implementation may be a bit slow, +// but it shows, how the SAX-Writer handles the allowLineBreak calls. +//-------------------------------------- +void writeParagraphHelper( + const Reference< XExtendedDocumentHandler > &r , + const OUString & s) +{ + int nMax = s.len(); + int nStart = 0; + + Sequence<sal_uInt16> seq( s.len() ); + memcpy( seq.getArray() , s.getStr() , s.len() * sizeof( sal_uInt16 ) ); + + for( int n = 1 ; n < nMax ; n++ ){ + if( 32 == seq.getArray()[n] ) { + r->allowLineBreak(); + r->characters( s.copy( nStart , n - nStart ) ); + nStart = n; + } + } + r->allowLineBreak(); + r->characters( s.copy( nStart , n - nStart ) ); +} + + +//--------------------------------- +// helper implementation for SAX-Writer +// writes data to a file +//-------------------------------- +class OFileWriter : + public WeakImplHelper1< XOutputStream > +{ +public: + OFileWriter( char *pcFile ) { strcpy( m_pcFile , pcFile ); m_f = 0; } + + +public: + virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL flush(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); + virtual void SAL_CALL closeOutput(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException); +private: + char m_pcFile[256]; + FILE *m_f; +}; + + +void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + if( ! m_f ) { + m_f = fopen( m_pcFile , "w" ); + } + + fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f ); +} + + +void OFileWriter::flush(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + fflush( m_f ); +} + +void OFileWriter::closeOutput(void) + throw (NotConnectedException, BufferSizeExceededException, RuntimeException) +{ + fclose( m_f ); + m_f = 0; +} + + + +// Needed to switch on solaris threads +#ifdef SOLARIS +extern "C" void ChangeGlobalInit(); +#endif +int main (int argc, char **argv) +{ + + if( argc < 3) { + printf( "usage : saxdemo inputfile outputfile\n" ); + exit( 0 ); + } +#ifdef SOLARIS + // switch on threads in solaris + ChangeGlobalInit(); +#endif + + // create service manager + Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" )) ); + + Reference < XImplementationRegistration > xReg; + try + { + // Create registration service + Reference < XInterface > x = xSMgr->createInstance( + OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) ); + xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY ); + } + catch( Exception & ) { + printf( "Couldn't create ImplementationRegistration service\n" ); + exit(1); + } + + OString sTestName; + try + { + // Load dll for the tested component +#ifdef SAL_W32 + OUString aDllName = OStringToOUString( "sax" , RTL_TEXTENCODING_ASCII_US ); +#else + OUString aDllName = OUString::createFromAscii( "lib" ); + aDllName += OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US ); + aDllName += OUString::createFromAscii( ".so" ); +#endif + xReg->registerImplementation( + OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ), + aDllName, + Reference< XSimpleRegistry > () ); + } + catch( Exception &e ) { + printf( "Couldn't reach sax dll\n" ); + printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() ); + + exit(1); + } + + + //-------------------------------- + // parser demo + // read xml from a file and count elements + //-------------------------------- + Reference< XInterface > x = xSMgr->createInstance( + OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) ); + if( x.is() ) + { + Reference< XParser > rParser( x , UNO_QUERY ); + + // create and connect the document handler to the parser + TestDocumentHandler *pDocHandler = new TestDocumentHandler( ); + + Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler ); + Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler ); + + rParser->setDocumentHandler( rDocHandler ); + rParser->setEntityResolver( rEntityResolver ); + + // create the input stream + InputSource source; + source.aInputStream = createStreamFromFile( argv[1] ); + source.sSystemId = OUString::createFromAscii( argv[1] ); + + try + { + // start parsing + rParser->parseStream( source ); + } + + catch( Exception & e ) + { + OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); + printf( "Exception during parsing : %s\n" , o1.getStr() ); + } + } + else + { + printf( "couln't create sax-parser component\n" ); + } + + + //---------------------- + // The SAX-Writer demo + //---------------------- + x= xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ); + if( x.is() ) + { + printf( "start writing to %s\n" , argv[2] ); + + OFileWriter *pw = new OFileWriter( argv[2] ); + Reference< XActiveDataSource > source( x , UNO_QUERY ); + source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) ); + + AttributeListImpl *pList = new AttributeListImpl; + Reference< XAttributeList > rList( (XAttributeList *) pList ); + + Reference< XExtendedDocumentHandler > r( x , UNO_QUERY ); + r->startDocument(); + + pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )), + OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("foo\n u")) ); + pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , + OUString( RTL_CONSTASCII_USTRINGPARAM("foo2")) ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList ); + // tells the writer to insert a linefeed + r->ignorableWhitespace( OUString() ); + + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) ); + r->ignorableWhitespace( OUString() ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList ); + r->ignorableWhitespace( OUString() ); + + // the enpassant must be converted & -> & + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("ü")) ); + r->ignorableWhitespace( OUString() ); + + // '>' must not be converted + r->startCDATA(); + r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(" > foo < ")) ); + r->endCDATA(); + r->ignorableWhitespace( OUString() ); + + OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( + "This is only a test to check, if the writer inserts line feeds " + "if needed or if the writer puts the whole text into one line." )); + writeParagraphHelper( r , testParagraph ); + + r->ignorableWhitespace( OUString() ); + r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("This is a comment !")) ); + r->ignorableWhitespace( OUString() ); + + r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList ); + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) ); + r->ignorableWhitespace( OUString() ); + + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) ); + r->ignorableWhitespace( OUString() ); + + r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) ); + r->endDocument(); + + printf( "finished writing\n" ); + } + else + { + printf( "couln't create sax-writer component\n" ); + } +} diff --git a/sax/test/testcomponent.cxx b/sax/test/testcomponent.cxx new file mode 100644 index 000000000000..582bf423bc48 --- /dev/null +++ b/sax/test/testcomponent.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * $RCSfile: testcomponent.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ + * + * 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): _______________________________________ + * + * + ************************************************************************/ + +//------------------------------------------------------ +// testcomponent - Loads a service and its testcomponent from dlls performs a test. +// Expands the dll-names depending on the actual environment. +// Example : testcomponent stardiv.uno.io.Pipe stm +// +// Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe +// + +#include <stdio.h> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +#include <com/sun/star/test/XSimpleTest.hpp> + +#include <cppuhelper/servicefactory.hxx> + +#include <vos/dynload.hxx> +#include <vos/diagnose.hxx> + +#include <assert.h> + + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::test; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +// Needed to switch on solaris threads +#ifdef SOLARIS +extern "C" void ChangeGlobalInit(); +#endif + +int main (int argc, char **argv) +{ + + if( argc < 3) { + printf( "usage : testcomponent service dll [additional dlls]\n" ); + exit( 0 ); + } +#ifdef SOLARIS + // switch on threads in solaris + ChangeGlobalInit(); +#endif + + // create service manager + Reference< XMultiServiceFactory > xSMgr = + createRegistryServiceFactory( OUString( RTL_CONSTASCII_USTRINGPARAM("applicat.rdb")) ); + + Reference < XImplementationRegistration > xReg; + Reference < XSimpleRegistry > xSimpleReg; + + try + { + // Create registration service + Reference < XInterface > x = xSMgr->createInstance( + OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) ); + xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY ); + } + catch( Exception & ) { + printf( "Couldn't create ImplementationRegistration service\n" ); + exit(1); + } + + sal_Char szBuf[1024]; + OString sTestName; + + try + { + // Load dll for the tested component + for( int n = 2 ; n <argc ; n ++ ) { +#ifdef SAL_W32 + OUString aDllName = OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US ); +#else + OUString aDllName = L"lib"; + aDllName += OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US ); + aDllName += L".so"; +#endif + xReg->registerImplementation( + OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ), + aDllName, + xSimpleReg ); + } + } + catch( Exception &e ) { + printf( "Couldn't reach dll %s\n" , szBuf ); + printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() ); + + exit(1); + } + + + try + { + // Load dll for the test component + sTestName = "test"; + sTestName += argv[2]; + +#ifdef SAL_W32 + OUString aDllName = OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US ); +#else + OUString aDllName = L"lib"; + aDllName += OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US ); + aDllName += L".so"; +#endif + + xReg->registerImplementation( + OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ) , + aDllName, + xSimpleReg ); + } + catch( Exception & e ) + { + printf( "Couldn't reach dll %s\n" , szBuf ); + exit(1); + } + + + // Instantiate test service + sTestName = "test."; + sTestName += argv[1]; + + Reference < XInterface > xIntTest = + xSMgr->createInstance( OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US ) ); + Reference< XSimpleTest > xTest( xIntTest , UNO_QUERY ); + + if( ! xTest.is() ) { + printf( "Couldn't instantiate test service \n" ); + exit( 1 ); + } + + + sal_Int32 nHandle = 0; + sal_Int32 nNewHandle; + sal_Int32 nErrorCount = 0; + sal_Int32 nWarningCount = 0; + + // loop until all test are performed + while( nHandle != -1 ) + { + // Instantiate serivce + Reference< XInterface > x = + xSMgr->createInstance( OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) ); + if( ! x.is() ) + { + printf( "Couldn't instantiate service !\n" ); + exit( 1 ); + } + + // do the test + try + { + nNewHandle = xTest->test( + OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) , x , nHandle ); + } + catch( Exception & e ) { + OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ); + printf( "testcomponent : uncaught exception %s\n" , o.getStr() ); + exit(1); + } + catch( ... ) + { + printf( "testcomponent : uncaught unknown exception\n" ); + exit(1); + } + + + // print errors and warning + Sequence<OUString> seqErrors = xTest->getErrors(); + Sequence<OUString> seqWarnings = xTest->getWarnings(); + if( seqWarnings.getLength() > nWarningCount ) + { + printf( "Warnings during test %d!\n" , nHandle ); + for( ; nWarningCount < seqWarnings.getLength() ; nWarningCount ++ ) + { + OString o = OUStringToOString( + seqWarnings.getArray()[nWarningCount], RTL_TEXTENCODING_ASCII_US ); + printf( "Warning\n%s\n---------\n" , o.getStr() ); + } + } + + + if( seqErrors.getLength() > nErrorCount ) { + printf( "Errors during test %d!\n" , nHandle ); + for( ; nErrorCount < seqErrors.getLength() ; nErrorCount ++ ) { + OString o = OUStringToOString( + seqErrors.getArray()[nErrorCount], RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + } + } + + nHandle = nNewHandle; + } + + if( xTest->testPassed() ) { + printf( "Test passed !\n" ); + } + else { + printf( "Test failed !\n" ); + } + + Reference <XComponent > rComp( xSMgr , UNO_QUERY ); + rComp->dispose(); + return 0; +} diff --git a/sax/util/makefile.mk b/sax/util/makefile.mk new file mode 100644 index 000000000000..bb4599c4ef86 --- /dev/null +++ b/sax/util/makefile.mk @@ -0,0 +1,93 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:43:13 $ +# +# 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): _______________________________________ +# +# +# +#************************************************************************* +PRJ=.. + +PRJNAME=sax +TARGET=sax +NO_BSYMBOLIC=TRUE +ENABLE_EXCEPTIONS=TRUE +# --- Settings ----------------------------------------------------- +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk +#----------------------------------------------------------- + + +SHL1TARGET= $(TARGET) +SHL1IMPLIB= i$(TARGET) + + +SHL1STDLIBS= \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB)\ + $(EXPAT3RDLIB) + +SHL1LIBS= $(SLB)$/expatwrap.lib + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) +DEF1EXPORTFILE= exports.dxp + +# --- Targets ------------------------------------------------------ +.INCLUDE : target.mk |