Bump for 3.6-28
[LibreOffice.git] / sax / test / saxdemo.cxx
bloba7e8f8a16ab5b2076b037f5315dc24d9b93931e9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 //------------------------------------------------------
30 // testcomponent - Loads a service and its testcomponent from dlls performs a test.
31 // Expands the dll-names depending on the actual environment.
32 // Example : testcomponent stardiv.uno.io.Pipe stm
34 // Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe
37 #include <stdio.h>
38 #include <vector>
39 #include <cstring>
41 #include <com/sun/star/registry/XImplementationRegistration.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
44 #include <com/sun/star/xml/sax/SAXParseException.hpp>
45 #include <com/sun/star/xml/sax/XParser.hpp>
46 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
48 #include <com/sun/star/io/XOutputStream.hpp>
49 #include <com/sun/star/io/XActiveDataSource.hpp>
51 #include <cppuhelper/servicefactory.hxx>
52 #include <cppuhelper/implbase1.hxx>
53 #include <cppuhelper/implbase3.hxx>
55 #include <osl/diagnose.h>
57 using namespace ::rtl;
58 using namespace ::std;
59 using namespace ::cppu;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::lang;
62 using namespace ::com::sun::star::registry;
63 using namespace ::com::sun::star::xml::sax;
64 using namespace ::com::sun::star::io;
67 /************
68 * Sequence of bytes -> InputStream
69 ************/
70 class OInputStream : public WeakImplHelper1 < XInputStream >
72 public:
73 OInputStream( const Sequence< sal_Int8 >&seq ) :
74 m_seq( seq ),
75 nPos( 0 )
78 public:
79 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
80 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
82 nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ?
83 m_seq.getLength() - nPos :
84 nBytesToRead;
85 aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead );
86 nPos += nBytesToRead;
87 return nBytesToRead;
89 virtual sal_Int32 SAL_CALL readSomeBytes(
90 ::com::sun::star::uno::Sequence< sal_Int8 >& aData,
91 sal_Int32 nMaxBytesToRead )
92 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
94 return readBytes( aData, nMaxBytesToRead );
96 virtual void SAL_CALL skipBytes( sal_Int32 /* nBytesToSkip */ )
97 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
99 // not implemented
101 virtual sal_Int32 SAL_CALL available( )
102 throw(NotConnectedException, IOException, RuntimeException)
104 return m_seq.getLength() - nPos;
106 virtual void SAL_CALL closeInput( )
107 throw(NotConnectedException, IOException, RuntimeException)
109 // not needed
111 Sequence< sal_Int8> m_seq;
112 sal_Int32 nPos;
115 //-------------------------------
116 // Helper : create an input stream from a file
117 //------------------------------
118 Reference< XInputStream > createStreamFromFile(
119 const char *pcFile )
121 FILE *f = fopen( pcFile , "rb" );
122 Reference< XInputStream > r;
124 if( f ) {
125 fseek( f , 0 , SEEK_END );
126 int nLength = ftell( f );
127 fseek( f , 0 , SEEK_SET );
129 Sequence<sal_Int8> seqIn(nLength);
130 fread( seqIn.getArray() , nLength , 1 , f );
132 r = Reference< XInputStream > ( new OInputStream( seqIn ) );
133 fclose( f );
135 return r;
138 //-----------------------------------------
139 // The document handler, which is needed for the saxparser
140 // The Documenthandler for reading sax
141 //-----------------------------------------
142 class TestDocumentHandler :
143 public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
145 public:
146 TestDocumentHandler( )
150 public: // Error handler
151 virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
153 printf( "Error !\n" );
154 throw SAXException(
155 OUString( "error from error handler") ,
156 Reference < XInterface >() ,
157 aSAXParseException );
159 virtual void SAL_CALL fatalError(const Any& /* aSAXParseException */) throw (SAXException, RuntimeException)
161 printf( "Fatal Error !\n" );
163 virtual void SAL_CALL warning(const Any& /* aSAXParseException */) throw (SAXException, RuntimeException)
165 printf( "Warning !\n" );
169 public: // ExtendedDocumentHandler
171 virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException)
173 m_iElementCount = 0;
174 m_iAttributeCount = 0;
175 m_iWhitespaceCount =0;
176 m_iCharCount=0;
177 printf( "document started\n" );
179 virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException)
181 printf( "document finished\n" );
182 printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
183 m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount );
186 virtual void SAL_CALL startElement(const OUString& /* aName */,
187 const Reference< XAttributeList > & xAttribs)
188 throw (SAXException,RuntimeException)
190 m_iElementCount ++;
191 m_iAttributeCount += xAttribs->getLength();
194 virtual void SAL_CALL endElement(const OUString& /* aName */) throw (SAXException,RuntimeException)
196 // ignored
199 virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
201 m_iCharCount += aChars.getLength();
203 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
205 m_iWhitespaceCount += aWhitespaces.getLength();
208 virtual void SAL_CALL processingInstruction(const OUString& /* aTarget */, const OUString& /* aData */) throw (SAXException,RuntimeException)
210 // ignored
213 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & /* xLocator */)
214 throw (SAXException,RuntimeException)
216 // ignored
219 virtual InputSource SAL_CALL resolveEntity(
220 const OUString& sPublicId,
221 const OUString& sSystemId)
222 throw (RuntimeException)
224 InputSource source;
225 source.sSystemId = sSystemId;
226 source.sPublicId = sPublicId;
228 source.aInputStream = createStreamFromFile(
229 OUStringToOString( sSystemId, RTL_TEXTENCODING_ASCII_US).getStr() );
231 return source;
234 virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
237 virtual void SAL_CALL endCDATA(void) throw (RuntimeException)
240 virtual void SAL_CALL comment(const OUString& /* sComment */) throw (SAXException,RuntimeException)
243 virtual void SAL_CALL unknown(const OUString& /* sString */) throw (SAXException,RuntimeException)
247 virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException )
252 public:
253 int m_iElementCount;
254 int m_iAttributeCount;
255 int m_iWhitespaceCount;
256 int m_iCharCount;
259 //--------------------------------------
260 // helper implementation for writing
261 // implements an XAttributeList
262 //-------------------------------------
263 struct AttributeListImpl_impl;
264 class AttributeListImpl : public WeakImplHelper1< XAttributeList >
266 public:
267 AttributeListImpl();
268 AttributeListImpl( const AttributeListImpl & );
269 ~AttributeListImpl();
271 public:
272 virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException);
273 virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException);
274 virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException);
275 virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException);
276 virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException);
277 virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException);
279 public:
280 void addAttribute( const OUString &sName ,
281 const OUString &sType ,
282 const OUString &sValue );
283 void clear();
285 private:
286 struct AttributeListImpl_impl *m_pImpl;
290 struct TagAttribute
292 TagAttribute(){}
293 TagAttribute( const OUString &s_Name,
294 const OUString &s_Type ,
295 const OUString &s_Value )
297 this->sName = s_Name;
298 this->sType = s_Type;
299 this->sValue = s_Value;
302 OUString sName;
303 OUString sType;
304 OUString sValue;
307 struct AttributeListImpl_impl
309 AttributeListImpl_impl()
311 // performance improvement during adding
312 vecAttribute.reserve(20);
314 vector<struct TagAttribute> vecAttribute;
319 sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException)
321 return (sal_Int16) m_pImpl->vecAttribute.size();
325 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
327 m_pImpl = new AttributeListImpl_impl;
328 *m_pImpl = *(r.m_pImpl);
331 OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException)
333 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
334 return m_pImpl->vecAttribute[i].sName;
336 return OUString();
340 OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
342 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
343 return m_pImpl->vecAttribute[i].sType;
345 return OUString();
348 OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException)
350 if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
351 return m_pImpl->vecAttribute[i].sValue;
353 return OUString();
357 OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException)
359 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
361 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
362 if( (*ii).sName == sName ) {
363 return (*ii).sType;
366 return OUString();
369 OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException)
371 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
373 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
374 if( (*ii).sName == sName ) {
375 return (*ii).sValue;
378 return OUString();
383 AttributeListImpl::AttributeListImpl()
385 m_pImpl = new AttributeListImpl_impl;
390 AttributeListImpl::~AttributeListImpl()
392 delete m_pImpl;
396 void AttributeListImpl::addAttribute( const OUString &sName ,
397 const OUString &sType ,
398 const OUString &sValue )
400 m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
403 void AttributeListImpl::clear()
405 m_pImpl->vecAttribute.clear();
409 //--------------------------------------
410 // helper function for writing
411 // ensures that linebreaks are inserted
412 // when writing a long text.
413 // Note: this implementation may be a bit slow,
414 // but it shows, how the SAX-Writer handles the allowLineBreak calls.
415 //--------------------------------------
416 void writeParagraphHelper(
417 const Reference< XExtendedDocumentHandler > &r ,
418 const OUString & s)
420 int nMax = s.getLength();
421 int nStart = 0;
422 int n = 1;
424 Sequence<sal_uInt16> seq( s.getLength() );
425 memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) );
427 for( n = 1 ; n < nMax ; n++ ){
428 if( 32 == seq.getArray()[n] ) {
429 r->allowLineBreak();
430 r->characters( s.copy( nStart , n - nStart ) );
431 nStart = n;
434 r->allowLineBreak();
435 r->characters( s.copy( nStart , n - nStart ) );
439 //---------------------------------
440 // helper implementation for SAX-Writer
441 // writes data to a file
442 //--------------------------------
443 class OFileWriter :
444 public WeakImplHelper1< XOutputStream >
446 public:
447 OFileWriter( char *pcFile ) { strncpy( m_pcFile , pcFile, 256 - 1 ); m_f = 0; }
450 public:
451 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
452 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
453 virtual void SAL_CALL flush(void)
454 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
455 virtual void SAL_CALL closeOutput(void)
456 throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
457 private:
458 char m_pcFile[256];
459 FILE *m_f;
463 void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData)
464 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
466 if( ! m_f ) {
467 m_f = fopen( m_pcFile , "w" );
470 fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f );
474 void OFileWriter::flush(void)
475 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
477 fflush( m_f );
480 void OFileWriter::closeOutput(void)
481 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
483 fclose( m_f );
484 m_f = 0;
489 // Needed to switch on solaris threads
490 #ifdef SOLARIS
491 extern "C" void ChangeGlobalInit();
492 #endif
493 int main (int argc, char **argv)
496 if( argc < 3) {
497 printf( "usage : saxdemo inputfile outputfile\n" );
498 exit( 0 );
500 #ifdef SOLARIS
501 // switch on threads in solaris
502 ChangeGlobalInit();
503 #endif
505 // create service manager
506 Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory(
507 OUString( "applicat.rdb" ) );
509 Reference < XImplementationRegistration > xReg;
512 // Create registration service
513 Reference < XInterface > x = xSMgr->createInstance(
514 OUString("com.sun.star.registry.ImplementationRegistration") );
515 xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY );
517 catch( Exception & ) {
518 printf( "Couldn't create ImplementationRegistration service\n" );
519 exit(1);
522 OString sTestName;
525 // Load dll for the tested component
526 OUString aDllName( "sax.uno" SAL_DLLEXTENSION );
527 xReg->registerImplementation(
528 OUString("com.sun.star.loader.SharedLibrary"),
529 aDllName,
530 Reference< XSimpleRegistry > () );
532 catch( Exception &e ) {
533 printf( "Couldn't reach sax dll\n" );
534 printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
536 exit(1);
540 //--------------------------------
541 // parser demo
542 // read xml from a file and count elements
543 //--------------------------------
544 Reference< XInterface > x = xSMgr->createInstance(
545 OUString("com.sun.star.xml.sax.Parser") );
546 if( x.is() )
548 Reference< XParser > rParser( x , UNO_QUERY );
550 // create and connect the document handler to the parser
551 TestDocumentHandler *pDocHandler = new TestDocumentHandler( );
553 Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler );
554 Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler );
556 rParser->setDocumentHandler( rDocHandler );
557 rParser->setEntityResolver( rEntityResolver );
559 // create the input stream
560 InputSource source;
561 source.aInputStream = createStreamFromFile( argv[1] );
562 source.sSystemId = OUString::createFromAscii( argv[1] );
566 // start parsing
567 rParser->parseStream( source );
570 catch( Exception & e )
572 OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
573 printf( "Exception during parsing : %s\n" , o1.getStr() );
576 else
578 printf( "couldn't create sax-parser component\n" );
582 //----------------------
583 // The SAX-Writer demo
584 //----------------------
585 x= xSMgr->createInstance( OUString("com.sun.star.xml.sax.Writer") );
586 if( x.is() )
588 printf( "start writing to %s\n" , argv[2] );
590 OFileWriter *pw = new OFileWriter( argv[2] );
591 Reference< XActiveDataSource > source( x , UNO_QUERY );
592 source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) );
594 AttributeListImpl *pList = new AttributeListImpl;
595 Reference< XAttributeList > rList( (XAttributeList *) pList );
597 Reference< XExtendedDocumentHandler > r( x , UNO_QUERY );
598 r->startDocument();
600 pList->addAttribute( OUString( "Arg1" ),
601 OUString( "CDATA") ,
602 OUString( "foo\n u") );
603 pList->addAttribute( OUString( "Arg2") ,
604 OUString( "CDATA") ,
605 OUString( "foo2") );
607 r->startElement( OUString( "tag1") , rList );
608 // tells the writer to insert a linefeed
609 r->ignorableWhitespace( OUString() );
611 r->characters( OUString( "huhu") );
612 r->ignorableWhitespace( OUString() );
614 r->startElement( OUString( "hi") , rList );
615 r->ignorableWhitespace( OUString() );
617 // the enpassant must be converted & -> &amp;
618 r->characters( OUString( "&#252;") );
619 r->ignorableWhitespace( OUString() );
621 // '>' must not be converted
622 r->startCDATA();
623 r->characters( OUString( " > foo < ") );
624 r->endCDATA();
625 r->ignorableWhitespace( OUString() );
627 OUString testParagraph = OUString(
628 "This is only a test to check, if the writer inserts line feeds "
629 "if needed or if the writer puts the whole text into one line." );
630 writeParagraphHelper( r , testParagraph );
632 r->ignorableWhitespace( OUString() );
633 r->comment( OUString( "This is a comment !") );
634 r->ignorableWhitespace( OUString() );
636 r->startElement( OUString( "emptytagtest") , rList );
637 r->endElement( OUString( "emptytagtest") );
638 r->ignorableWhitespace( OUString() );
640 r->endElement( OUString( "hi") );
641 r->ignorableWhitespace( OUString() );
643 r->endElement( OUString( "tag1") );
644 r->endDocument();
646 printf( "finished writing\n" );
648 else
650 printf( "couldn't create sax-writer component\n" );
654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */