1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: saxdemo.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 //------------------------------------------------------
32 // testcomponent - Loads a service and its testcomponent from dlls performs a test.
33 // Expands the dll-names depending on the actual environment.
34 // Example : testcomponent stardiv.uno.io.Pipe stm
36 // Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe
42 #include <com/sun/star/registry/XImplementationRegistration.hpp>
43 #include <com/sun/star/lang/XComponent.hpp>
45 #include <com/sun/star/xml/sax/SAXParseException.hpp>
46 #include <com/sun/star/xml/sax/XParser.hpp>
47 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
49 #include <com/sun/star/io/XOutputStream.hpp>
50 #include <com/sun/star/io/XActiveDataSource.hpp>
52 #include <cppuhelper/servicefactory.hxx>
53 #include <cppuhelper/implbase1.hxx>
54 #include <cppuhelper/implbase3.hxx>
56 #include <vos/dynload.hxx>
57 #include <vos/diagnose.hxx>
59 using namespace ::rtl
;
60 using namespace ::std
;
61 using namespace ::cppu
;
62 using namespace ::com::sun::star::uno
;
63 using namespace ::com::sun::star::lang
;
64 using namespace ::com::sun::star::registry
;
65 using namespace ::com::sun::star::xml::sax
;
66 using namespace ::com::sun::star::io
;
70 * Sequence of bytes -> InputStream
72 class OInputStream
: public WeakImplHelper1
< XInputStream
>
75 OInputStream( const Sequence
< sal_Int8
>&seq
) :
81 virtual sal_Int32 SAL_CALL
readBytes( Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
82 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
84 nBytesToRead
= (nBytesToRead
> m_seq
.getLength() - nPos
) ?
85 m_seq
.getLength() - nPos
:
87 aData
= Sequence
< sal_Int8
> ( &(m_seq
.getConstArray()[nPos
]) , nBytesToRead
);
91 virtual sal_Int32 SAL_CALL
readSomeBytes(
92 ::com::sun::star::uno::Sequence
< sal_Int8
>& aData
,
93 sal_Int32 nMaxBytesToRead
)
94 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
96 return readBytes( aData
, nMaxBytesToRead
);
98 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
)
99 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
103 virtual sal_Int32 SAL_CALL
available( )
104 throw(NotConnectedException
, IOException
, RuntimeException
)
106 return m_seq
.getLength() - nPos
;
108 virtual void SAL_CALL
closeInput( )
109 throw(NotConnectedException
, IOException
, RuntimeException
)
114 Sequence
< sal_Int8
> m_seq
;
117 //-------------------------------
118 // Helper : create an input stream from a file
119 //------------------------------
120 Reference
< XInputStream
> createStreamFromFile(
123 FILE *f
= fopen( pcFile
, "rb" );
124 Reference
< XInputStream
> r
;
127 fseek( f
, 0 , SEEK_END
);
128 int nLength
= ftell( f
);
129 fseek( f
, 0 , SEEK_SET
);
131 Sequence
<sal_Int8
> seqIn(nLength
);
132 fread( seqIn
.getArray() , nLength
, 1 , f
);
134 r
= Reference
< XInputStream
> ( new OInputStream( seqIn
) );
140 //-----------------------------------------
141 // The document handler, which is needed for the saxparser
142 // The Documenthandler for reading sax
143 //-----------------------------------------
144 class TestDocumentHandler
:
145 public WeakImplHelper3
< XExtendedDocumentHandler
, XEntityResolver
, XErrorHandler
>
148 TestDocumentHandler( )
152 public: // Error handler
153 virtual void SAL_CALL
error(const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
155 printf( "Error !\n" );
157 OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) ,
158 Reference
< XInterface
>() ,
159 aSAXParseException
);
161 virtual void SAL_CALL
fatalError(const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
163 printf( "Fatal Error !\n" );
165 virtual void SAL_CALL
warning(const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
167 printf( "Warning !\n" );
171 public: // ExtendedDocumentHandler
173 virtual void SAL_CALL
startDocument(void) throw (SAXException
, RuntimeException
)
176 m_iAttributeCount
= 0;
177 m_iWhitespaceCount
=0;
179 printf( "document started\n" );
181 virtual void SAL_CALL
endDocument(void) throw (SAXException
, RuntimeException
)
183 printf( "document finished\n" );
184 printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
185 m_iElementCount
, m_iAttributeCount
, m_iWhitespaceCount
, m_iCharCount
);
188 virtual void SAL_CALL
startElement(const OUString
& aName
,
189 const Reference
< XAttributeList
> & xAttribs
)
190 throw (SAXException
,RuntimeException
)
193 m_iAttributeCount
+= xAttribs
->getLength();
196 virtual void SAL_CALL
endElement(const OUString
& aName
) throw (SAXException
,RuntimeException
)
201 virtual void SAL_CALL
characters(const OUString
& aChars
) throw (SAXException
,RuntimeException
)
203 m_iCharCount
+= aChars
.getLength();
205 virtual void SAL_CALL
ignorableWhitespace(const OUString
& aWhitespaces
) throw (SAXException
,RuntimeException
)
207 m_iWhitespaceCount
+= aWhitespaces
.getLength();
210 virtual void SAL_CALL
processingInstruction(const OUString
& aTarget
, const OUString
& aData
) throw (SAXException
,RuntimeException
)
215 virtual void SAL_CALL
setDocumentLocator(const Reference
< XLocator
> & xLocator
)
216 throw (SAXException
,RuntimeException
)
221 virtual InputSource SAL_CALL
resolveEntity(
222 const OUString
& sPublicId
,
223 const OUString
& sSystemId
)
224 throw (SAXException
,RuntimeException
)
227 source
.sSystemId
= sSystemId
;
228 source
.sPublicId
= sPublicId
;
230 source
.aInputStream
= createStreamFromFile(
231 OUStringToOString( sSystemId
, RTL_TEXTENCODING_ASCII_US
) );
236 virtual void SAL_CALL
startCDATA(void) throw (SAXException
,RuntimeException
)
239 virtual void SAL_CALL
endCDATA(void) throw (SAXException
,RuntimeException
)
242 virtual void SAL_CALL
comment(const OUString
& sComment
) throw (SAXException
,RuntimeException
)
245 virtual void SAL_CALL
unknown(const OUString
& sString
) throw (SAXException
,RuntimeException
)
249 virtual void SAL_CALL
allowLineBreak( void) throw (SAXException
, RuntimeException
)
256 int m_iAttributeCount
;
257 int m_iWhitespaceCount
;
261 //--------------------------------------
262 // helper implementation for writing
263 // implements an XAttributeList
264 //-------------------------------------
265 struct AttributeListImpl_impl
;
266 class AttributeListImpl
: public WeakImplHelper1
< XAttributeList
>
270 AttributeListImpl( const AttributeListImpl
& );
271 ~AttributeListImpl();
274 virtual sal_Int16 SAL_CALL
getLength(void) throw (RuntimeException
);
275 virtual OUString SAL_CALL
getNameByIndex(sal_Int16 i
) throw (RuntimeException
);
276 virtual OUString SAL_CALL
getTypeByIndex(sal_Int16 i
) throw (RuntimeException
);
277 virtual OUString SAL_CALL
getTypeByName(const OUString
& aName
) throw (RuntimeException
);
278 virtual OUString SAL_CALL
getValueByIndex(sal_Int16 i
) throw (RuntimeException
);
279 virtual OUString SAL_CALL
getValueByName(const OUString
& aName
) throw (RuntimeException
);
282 void addAttribute( const OUString
&sName
,
283 const OUString
&sType
,
284 const OUString
&sValue
);
288 struct AttributeListImpl_impl
*m_pImpl
;
295 TagAttribute( const OUString
&sName
,
296 const OUString
&sType
,
297 const OUString
&sValue
)
301 this->sValue
= sValue
;
309 struct AttributeListImpl_impl
311 AttributeListImpl_impl()
313 // performance improvement during adding
314 vecAttribute
.reserve(20);
316 vector
<struct TagAttribute
> vecAttribute
;
321 sal_Int16
AttributeListImpl::getLength(void) throw (RuntimeException
)
323 return m_pImpl
->vecAttribute
.size();
327 AttributeListImpl::AttributeListImpl( const AttributeListImpl
&r
)
329 m_pImpl
= new AttributeListImpl_impl
;
330 *m_pImpl
= *(r
.m_pImpl
);
333 OUString
AttributeListImpl::getNameByIndex(sal_Int16 i
) throw (RuntimeException
)
335 if( i
< m_pImpl
->vecAttribute
.size() ) {
336 return m_pImpl
->vecAttribute
[i
].sName
;
342 OUString
AttributeListImpl::getTypeByIndex(sal_Int16 i
) throw (RuntimeException
)
344 if( i
< m_pImpl
->vecAttribute
.size() ) {
345 return m_pImpl
->vecAttribute
[i
].sType
;
350 OUString
AttributeListImpl::getValueByIndex(sal_Int16 i
) throw (RuntimeException
)
352 if( i
< m_pImpl
->vecAttribute
.size() ) {
353 return m_pImpl
->vecAttribute
[i
].sValue
;
359 OUString
AttributeListImpl::getTypeByName( const OUString
& sName
) throw (RuntimeException
)
361 vector
<struct TagAttribute
>::iterator ii
= m_pImpl
->vecAttribute
.begin();
363 for( ; ii
!= m_pImpl
->vecAttribute
.end() ; ii
++ ) {
364 if( (*ii
).sName
== sName
) {
371 OUString
AttributeListImpl::getValueByName(const OUString
& sName
) throw (RuntimeException
)
373 vector
<struct TagAttribute
>::iterator ii
= m_pImpl
->vecAttribute
.begin();
375 for( ; ii
!= m_pImpl
->vecAttribute
.end() ; ii
++ ) {
376 if( (*ii
).sName
== sName
) {
385 AttributeListImpl::AttributeListImpl()
387 m_pImpl
= new AttributeListImpl_impl
;
392 AttributeListImpl::~AttributeListImpl()
398 void AttributeListImpl::addAttribute( const OUString
&sName
,
399 const OUString
&sType
,
400 const OUString
&sValue
)
402 m_pImpl
->vecAttribute
.push_back( TagAttribute( sName
, sType
, sValue
) );
405 void AttributeListImpl::clear()
407 m_pImpl
->vecAttribute
.clear();
411 //--------------------------------------
412 // helper function for writing
413 // ensures that linebreaks are inserted
414 // when writing a long text.
415 // Note: this implementation may be a bit slow,
416 // but it shows, how the SAX-Writer handles the allowLineBreak calls.
417 //--------------------------------------
418 void writeParagraphHelper(
419 const Reference
< XExtendedDocumentHandler
> &r
,
422 int nMax
= s
.getLength();
425 Sequence
<sal_uInt16
> seq( s
.getLength() );
426 memcpy( seq
.getArray() , s
.getStr() , s
.getLength() * sizeof( sal_uInt16
) );
428 for( int n
= 1 ; n
< nMax
; n
++ ){
429 if( 32 == seq
.getArray()[n
] ) {
431 r
->characters( s
.copy( nStart
, n
- nStart
) );
436 r
->characters( s
.copy( nStart
, n
- nStart
) );
440 //---------------------------------
441 // helper implementation for SAX-Writer
442 // writes data to a file
443 //--------------------------------
445 public WeakImplHelper1
< XOutputStream
>
448 OFileWriter( char *pcFile
) { strncpy( m_pcFile
, pcFile
, 256 - 1 ); m_f
= 0; }
452 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
)
453 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
454 virtual void SAL_CALL
flush(void)
455 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
456 virtual void SAL_CALL
closeOutput(void)
457 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
);
464 void OFileWriter::writeBytes(const Sequence
< sal_Int8
>& aData
)
465 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
468 m_f
= fopen( m_pcFile
, "w" );
471 fwrite( aData
.getConstArray() , 1 , aData
.getLength() , m_f
);
475 void OFileWriter::flush(void)
476 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
481 void OFileWriter::closeOutput(void)
482 throw (NotConnectedException
, BufferSizeExceededException
, RuntimeException
)
490 // Needed to switch on solaris threads
492 extern "C" void ChangeGlobalInit();
494 int main (int argc
, char **argv
)
498 printf( "usage : saxdemo inputfile outputfile\n" );
502 // switch on threads in solaris
506 // create service manager
507 Reference
< XMultiServiceFactory
> xSMgr
= createRegistryServiceFactory(
508 OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" )) );
510 Reference
< XImplementationRegistration
> xReg
;
513 // Create registration service
514 Reference
< XInterface
> x
= xSMgr
->createInstance(
515 OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) );
516 xReg
= Reference
< XImplementationRegistration
> ( x
, UNO_QUERY
);
518 catch( Exception
& ) {
519 printf( "Couldn't create ImplementationRegistration service\n" );
526 // Load dll for the tested component
528 OUString::createFromAscii( "sax.uno" SAL_DLLEXTENSION
);
529 xReg
->registerImplementation(
530 OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
532 Reference
< XSimpleRegistry
> () );
534 catch( Exception
&e
) {
535 printf( "Couldn't reach sax dll\n" );
536 printf( "%s\n" , OUStringToOString( e
.Message
, RTL_TEXTENCODING_ASCII_US
).getStr() );
542 //--------------------------------
544 // read xml from a file and count elements
545 //--------------------------------
546 Reference
< XInterface
> x
= xSMgr
->createInstance(
547 OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) );
550 Reference
< XParser
> rParser( x
, UNO_QUERY
);
552 // create and connect the document handler to the parser
553 TestDocumentHandler
*pDocHandler
= new TestDocumentHandler( );
555 Reference
< XDocumentHandler
> rDocHandler( (XDocumentHandler
*) pDocHandler
);
556 Reference
< XEntityResolver
> rEntityResolver( (XEntityResolver
*) pDocHandler
);
558 rParser
->setDocumentHandler( rDocHandler
);
559 rParser
->setEntityResolver( rEntityResolver
);
561 // create the input stream
563 source
.aInputStream
= createStreamFromFile( argv
[1] );
564 source
.sSystemId
= OUString::createFromAscii( argv
[1] );
569 rParser
->parseStream( source
);
572 catch( Exception
& e
)
574 OString o1
= OUStringToOString(e
.Message
, RTL_TEXTENCODING_UTF8
);
575 printf( "Exception during parsing : %s\n" , o1
.getStr() );
580 printf( "couln't create sax-parser component\n" );
584 //----------------------
585 // The SAX-Writer demo
586 //----------------------
587 x
= xSMgr
->createInstance( OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) );
590 printf( "start writing to %s\n" , argv
[2] );
592 OFileWriter
*pw
= new OFileWriter( argv
[2] );
593 Reference
< XActiveDataSource
> source( x
, UNO_QUERY
);
594 source
->setOutputStream( Reference
< XOutputStream
> ( (XOutputStream
*) pw
) );
596 AttributeListImpl
*pList
= new AttributeListImpl
;
597 Reference
< XAttributeList
> rList( (XAttributeList
*) pList
);
599 Reference
< XExtendedDocumentHandler
> r( x
, UNO_QUERY
);
602 pList
->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )),
603 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
604 OUString( RTL_CONSTASCII_USTRINGPARAM("foo\n u")) );
605 pList
->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) ,
606 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
607 OUString( RTL_CONSTASCII_USTRINGPARAM("foo2")) );
609 r
->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList
);
610 // tells the writer to insert a linefeed
611 r
->ignorableWhitespace( OUString() );
613 r
->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
614 r
->ignorableWhitespace( OUString() );
616 r
->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList
);
617 r
->ignorableWhitespace( OUString() );
619 // the enpassant must be converted & -> &
620 r
->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("ü")) );
621 r
->ignorableWhitespace( OUString() );
623 // '>' must not be converted
625 r
->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(" > foo < ")) );
627 r
->ignorableWhitespace( OUString() );
629 OUString testParagraph
= OUString( RTL_CONSTASCII_USTRINGPARAM(
630 "This is only a test to check, if the writer inserts line feeds "
631 "if needed or if the writer puts the whole text into one line." ));
632 writeParagraphHelper( r
, testParagraph
);
634 r
->ignorableWhitespace( OUString() );
635 r
->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("This is a comment !")) );
636 r
->ignorableWhitespace( OUString() );
638 r
->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList
);
639 r
->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) );
640 r
->ignorableWhitespace( OUString() );
642 r
->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) );
643 r
->ignorableWhitespace( OUString() );
645 r
->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) );
648 printf( "finished writing\n" );
652 printf( "couln't create sax-writer component\n" );