/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org 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 version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_extensions.hxx" #include #include #include // for the multiservice-factories #include #include #include #include #include #include #include #include #include #include #include #include // for EXTERN_SERVICE_CALLTYPE using namespace std; using namespace rtl; using namespace usr; #define BUILD_ERROR(expr, Message)\ {\ m_seqErrors.realloc( m_seqErrors.getLen() + 1 ); \ m_seqExceptions.realloc( m_seqExceptions.getLen() + 1 ); \ String str; \ str += __FILE__;\ str += " "; \ str += "(" ; \ str += __LINE__ ;\ str += ")\n";\ str += "[ " ; \ str += #expr; \ str += " ] : " ; \ str += Message; \ m_seqErrors.getArray()[ m_seqErrors.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \ }\ ((void)0) #define WARNING_ASSERT(expr, Message) \ if( ! (expr) ) { \ m_seqWarnings.realloc( m_seqErrors.getLen() +1 ); \ String str;\ str += __FILE__;\ str += " "; \ str += "(" ; \ str += __LINE__ ;\ str += ")\n";\ str += "[ " ; \ str += #expr; \ str += " ] : " ; \ str += Message; \ m_seqWarnings.getArray()[ m_seqWarnings.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \ 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.getLen()-1] = UsrAny( Exception );\ return; \ } \ ((void)0) /**** * test szenarios : * * * ****/ class OFileWriter : public XOutputStream, public OWeakObject { public: OFileWriter( char *pcFile ) { strcpy( m_pcFile , pcFile ); m_f = 0; } public: // refcounting BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ) { if( XOutputStream::getSmartUik() == aUik ) { rOut = (XOutputStream *) this; } else return OWeakObject::queryInterface( aUik , rOut ); return TRUE; } void acquire() { OWeakObject::acquire(); } void release() { OWeakObject::release(); } void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } public: virtual void writeBytes(const Sequence< BYTE >& aData) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ); virtual void flush(void) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ); virtual void closeOutput(void) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ); private: char m_pcFile[256]; FILE *m_f; }; void OFileWriter::writeBytes(const Sequence< BYTE >& aData) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ) { if( ! m_f ) { m_f = fopen( m_pcFile , "w" ); } fwrite( aData.getConstArray() , 1 , aData.getLen() , m_f ); } void OFileWriter::flush(void) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ) { fflush( m_f ); } void OFileWriter::closeOutput(void) THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) ) { fclose( m_f ); m_f = 0; } class OSaxWriterTest : public XSimpleTest, public OWeakObject { public: OSaxWriterTest( const XMultiServiceFactoryRef & rFactory ) : m_rFactory( rFactory ) { } ~OSaxWriterTest() {} public: // refcounting BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); void acquire() { OWeakObject::acquire(); } void release() { OWeakObject::release(); } void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } public: virtual void testInvariant(const UString& TestName, const XInterfaceRef& TestObject) THROWS( ( IllegalArgumentException, UsrSystemException) ); virtual INT32 test( const UString& TestName, const XInterfaceRef& TestObject, INT32 hTestHandle) THROWS( ( IllegalArgumentException, UsrSystemException) ); virtual BOOL testPassed(void) THROWS( ( UsrSystemException) ); virtual Sequence< UString > getErrors(void) THROWS( (UsrSystemException) ); virtual Sequence< UsrAny > getErrorExceptions(void) THROWS( (UsrSystemException) ); virtual Sequence< UString > getWarnings(void) THROWS( (UsrSystemException) ); private: void testSimple( const XExtendedDocumentHandlerRef &r ); void testExceptions( const XExtendedDocumentHandlerRef &r ); void testDTD( const XExtendedDocumentHandlerRef &r ); void testPerformance( const XExtendedDocumentHandlerRef &r ); void writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s); private: Sequence m_seqExceptions; Sequence m_seqErrors; Sequence m_seqWarnings; XMultiServiceFactoryRef m_rFactory; }; /*---------------------------------------- * * Attributlist implementation * *----------------------------------------*/ struct AttributeListImpl_impl; class AttributeListImpl : public XAttributeList, public OWeakObject { public: AttributeListImpl(); AttributeListImpl( const AttributeListImpl & ); ~AttributeListImpl(); public: BOOL queryInterface( Uik aUik, XInterfaceRef & rOut ); void acquire() { OWeakObject::acquire(); } void release() { OWeakObject::release(); } void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); } public: virtual INT16 getLength(void) THROWS( (UsrSystemException) ); virtual UString getNameByIndex(INT16 i) THROWS( (UsrSystemException) ); virtual UString getTypeByIndex(INT16 i) THROWS( (UsrSystemException) ); virtual UString getTypeByName(const UString& aName) THROWS( (UsrSystemException) ); virtual UString getValueByIndex(INT16 i) THROWS( (UsrSystemException) ); virtual UString getValueByName(const UString& aName) THROWS( (UsrSystemException) ); public: void addAttribute( const UString &sName , const UString &sType , const UString &sValue ); void clear(); private: struct AttributeListImpl_impl *m_pImpl; }; struct TagAttribute { TagAttribute(){} TagAttribute( const UString &sName, const UString &sType , const UString &sValue ) { this->sName = sName; this->sType = sType; this->sValue = sValue; } UString sName; UString sType; UString sValue; }; struct AttributeListImpl_impl { AttributeListImpl_impl() { // performance improvement during adding vecAttribute.reserve(20); } vector vecAttribute; }; INT16 AttributeListImpl::getLength(void) THROWS( (UsrSystemException) ) { return m_pImpl->vecAttribute.size(); } AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) { m_pImpl = new AttributeListImpl_impl; *m_pImpl = *(r.m_pImpl); } UString AttributeListImpl::getNameByIndex(INT16 i) THROWS( (UsrSystemException) ) { if( i < m_pImpl->vecAttribute.size() ) { return m_pImpl->vecAttribute[i].sName; } return UString(); } UString AttributeListImpl::getTypeByIndex(INT16 i) THROWS( (UsrSystemException) ) { if( i < m_pImpl->vecAttribute.size() ) { return m_pImpl->vecAttribute[i].sType; } return UString(); } UString AttributeListImpl::getValueByIndex(INT16 i) THROWS( (UsrSystemException) ) { if( i < m_pImpl->vecAttribute.size() ) { return m_pImpl->vecAttribute[i].sValue; } return UString(); } UString AttributeListImpl::getTypeByName( const UString& sName ) THROWS( (UsrSystemException) ) { vector::iterator ii = m_pImpl->vecAttribute.begin(); for (; ii != m_pImpl->vecAttribute.end(); ++ii) { if( (*ii).sName == sName ) { return (*ii).sType; } } return UString(); } UString AttributeListImpl::getValueByName(const UString& sName) THROWS( (UsrSystemException) ) { vector::iterator ii = m_pImpl->vecAttribute.begin(); for (; ii != m_pImpl->vecAttribute.end(); ++ii) { if( (*ii).sName == sName ) { return (*ii).sValue; } } return UString(); } BOOL AttributeListImpl::queryInterface( Uik aUik, XInterfaceRef & rOut ) { if( aUik == XAttributeList::getSmartUik() ) { rOut = (XAttributeList * )this; } else { return OWeakObject::queryInterface( aUik , rOut ); } return TRUE; } AttributeListImpl::AttributeListImpl() { m_pImpl = new AttributeListImpl_impl; } AttributeListImpl::~AttributeListImpl() { delete m_pImpl; } void AttributeListImpl::addAttribute( const UString &sName , const UString &sType , const UString &sValue ) { m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) ); } void AttributeListImpl::clear() { vector dummy; m_pImpl->vecAttribute.swap( dummy ); OSL_ASSERT( ! getLength() ); } /** * for external binding * * **/ XInterfaceRef OSaxWriterTest_CreateInstance( const XMultiServiceFactoryRef & rSMgr ) THROWS((Exception)) { OSaxWriterTest *p = new OSaxWriterTest( rSMgr ); XInterfaceRef xService = *p; return xService; } UString OSaxWriterTest_getServiceName( ) THROWS( () ) { return L"test.com.sun.star.xml.sax.Writer"; } UString OSaxWriterTest_getImplementationName( ) THROWS( () ) { return L"test.extensions.xml.sax.Writer"; } Sequence OSaxWriterTest_getSupportedServiceNames( ) THROWS( () ) { Sequence aRet(1); aRet.getArray()[0] = OSaxWriterTest_getImplementationName( ); return aRet; } BOOL OSaxWriterTest::queryInterface( Uik uik , XInterfaceRef &rOut ) { if( XSimpleTest::getSmartUik() == uik ) { rOut = (XSimpleTest *) this; } else { return OWeakObject::queryInterface( uik , rOut ); } return TRUE; } void OSaxWriterTest::testInvariant( const UString& TestName, const XInterfaceRef& TestObject ) THROWS( ( IllegalArgumentException, UsrSystemException) ) { if( L"com.sun.star.xml.sax.Writer" == TestName ) { XDocumentHandlerRef doc( TestObject , USR_QUERY ); XExtendedDocumentHandlerRef ext( TestObject , USR_QUERY ); XActiveDataSourceRef source( TestObject , USR_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" ); } } INT32 OSaxWriterTest::test( const UString& TestName, const XInterfaceRef& TestObject, INT32 hTestHandle) THROWS( ( IllegalArgumentException, UsrSystemException) ) { if( L"com.sun.star.xml.sax.Writer" == TestName ) { try { if( 0 == hTestHandle ) { testInvariant( TestName , TestObject ); } else { XExtendedDocumentHandlerRef writer( TestObject , USR_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 ) { BUILD_ERROR( 0 , UStringToString( e.getName() , CHARSET_SYSTEM ).GetCharStr() ); } 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; } BOOL OSaxWriterTest::testPassed(void) THROWS( (UsrSystemException) ) { return m_seqErrors.getLen() == 0; } Sequence< UString > OSaxWriterTest::getErrors(void) THROWS( (UsrSystemException) ) { return m_seqErrors; } Sequence< UsrAny > OSaxWriterTest::getErrorExceptions(void) THROWS( (UsrSystemException) ) { return m_seqExceptions; } Sequence< UString > OSaxWriterTest::getWarnings(void) THROWS( (UsrSystemException) ) { return m_seqWarnings; } void OSaxWriterTest::writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s) { int nMax = s.len(); int nStart = 0; Sequence seq( s.len() ); memcpy( seq.getArray() , s.getStr() , s.len() * sizeof( 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 XExtendedDocumentHandlerRef &r ) { UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter " L"wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile " L"bis zum bitteren Ende schreibt."; OFileWriter *pw = new OFileWriter("output.xml"); AttributeListImpl *pList = new AttributeListImpl; XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY ); XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY ); XActiveDataSourceRef source( r , USR_QUERY ); ERROR_ASSERT( ref.is() , "no output stream" ); ERROR_ASSERT( source.is() , "no active data source" ); source->setOutputStream( ref ); r->startDocument(); pList->addAttribute( L"Arg1" , L"CDATA" , L"bla\n u" ); pList->addAttribute( L"Arg2" , L"CDATA" , L"blub" ); r->startElement( L"tag1" , rList ); r->ignorableWhitespace( L"" ); r->characters( L"huhu" ); r->ignorableWhitespace( L"" ); r->startElement( L"hi" , rList ); r->ignorableWhitespace( L"" ); // the enpassant must be converted & -> & r->characters( L"ü" ); // Test added for mib. Tests if errors during conversions occurs r->ignorableWhitespace( UString() ); sal_Char array[256]; for( sal_Int32 n = 32 ; n < 254 ; n ++ ) { array[n-32] = n; } array[254-32] = 0; r->characters( StringToUString( array , RTL_TEXTENCODING_SYMBOL ) ); r->ignorableWhitespace( UString() ); // '>' must not be converted r->startCDATA(); r->characters( L">fsfsdf<" ); r->endCDATA(); r->ignorableWhitespace( UString() ); writeParagraph( r , testParagraph ); r->ignorableWhitespace( UString() ); r->comment( L"Dies ist ein Kommentar !" ); r->ignorableWhitespace( UString() ); r->startElement( L"emptytagtest" , rList ); r->endElement( L"emptytagtest" ); r->endElement( L"hi" ); r->ignorableWhitespace( L"" ); r->endElement( L"tag1" ); r->endDocument(); } void OSaxWriterTest::testExceptions( const XExtendedDocumentHandlerRef & r ) { OFileWriter *pw = new OFileWriter("output2.xml"); AttributeListImpl *pList = new AttributeListImpl; XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY ); XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY ); XActiveDataSourceRef source( r , USR_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 BOOL bException = TRUE; try { r->startElement( L"huhu" , rList ); bException = FALSE; } catch( SAXException& e ) { } ERROR_ASSERT( bException , "expected exception not thrown !" ); } r->startDocument(); r->startElement( L"huhu" , rList ); r->startCDATA(); { BOOL bException = TRUE; try { r->startElement( L"huhu" , rList ); bException = FALSE; } catch( SAXException& e ) { } ERROR_ASSERT( bException , "expected exception not thrown !" ); } r->endCDATA(); r->endElement( L"hi" ); r->endDocument(); } void OSaxWriterTest::testDTD(const XExtendedDocumentHandlerRef &r ) { OFileWriter *pw = new OFileWriter("outputDTD.xml"); AttributeListImpl *pList = new AttributeListImpl; XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY ); XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY ); XActiveDataSourceRef source( r , USR_QUERY ); ERROR_ASSERT( ref.is() , "no output stream" ); ERROR_ASSERT( source.is() , "no active data source" ); source->setOutputStream( ref ); r->startDocument(); r->unknown( L"\n" ); r->startElement( L"huhu" , rList ); r->endElement( L"huhu" ); r->endDocument(); } void OSaxWriterTest::testPerformance(const XExtendedDocumentHandlerRef &r ) { OFileWriter *pw = new OFileWriter("testPerformance.xml"); AttributeListImpl *pList = new AttributeListImpl; UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter " L"wohl > Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile " L"bis zum bitteren Ende schreibt."; XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY ); XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY ); XActiveDataSourceRef source( r , USR_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( UString( L"tag" ) + UString::valueOf( i2 ), rList ); for( sal_Int32 i = 0 ; i < 450 ; i ++ ) { r->ignorableWhitespace( L""); r->startElement( L"huhu" , rList ); r->characters( testParagraph ); // writeParagraph( r , testParagraph ); r->ignorableWhitespace( L""); r->endElement( L"huhu" ); } } for( i2 = 14 ; i2 >= 0 ; i2-- ) { r->ignorableWhitespace( L""); r->endElement( UString( L"tag" ) + UString::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 ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */