1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 //------------------------------------------------------ 29 // testcomponent - Loads a service and its testcomponent from dlls performs a test. 30 // Expands the dll-names depending on the actual environment. 31 // Example : testcomponent stardiv.uno.io.Pipe stm 32 // 33 // Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe 34 // 35 36 #include <stdio.h> 37 #include <vector> 38 39 #include <com/sun/star/registry/XImplementationRegistration.hpp> 40 #include <com/sun/star/lang/XComponent.hpp> 41 42 #include <com/sun/star/xml/sax/SAXParseException.hpp> 43 #include <com/sun/star/xml/sax/XParser.hpp> 44 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 45 46 #include <com/sun/star/io/XOutputStream.hpp> 47 #include <com/sun/star/io/XActiveDataSource.hpp> 48 49 #include <cppuhelper/servicefactory.hxx> 50 #include <cppuhelper/implbase1.hxx> 51 #include <cppuhelper/implbase3.hxx> 52 53 #include <vos/dynload.hxx> 54 #include <vos/diagnose.hxx> 55 56 using namespace ::rtl; 57 using namespace ::std; 58 using namespace ::cppu; 59 using namespace ::com::sun::star::uno; 60 using namespace ::com::sun::star::lang; 61 using namespace ::com::sun::star::registry; 62 using namespace ::com::sun::star::xml::sax; 63 using namespace ::com::sun::star::io; 64 65 66 /************ 67 * Sequence of bytes -> InputStream 68 ************/ 69 class OInputStream : public WeakImplHelper1 < XInputStream > 70 { 71 public: 72 OInputStream( const Sequence< sal_Int8 >&seq ) : 73 m_seq( seq ), 74 nPos( 0 ) 75 {} 76 77 public: 78 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 79 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 80 { 81 nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ? 82 m_seq.getLength() - nPos : 83 nBytesToRead; 84 aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead ); 85 nPos += nBytesToRead; 86 return nBytesToRead; 87 } 88 virtual sal_Int32 SAL_CALL readSomeBytes( 89 ::com::sun::star::uno::Sequence< sal_Int8 >& aData, 90 sal_Int32 nMaxBytesToRead ) 91 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 92 { 93 return readBytes( aData, nMaxBytesToRead ); 94 } 95 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) 96 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 97 { 98 // not implemented 99 } 100 virtual sal_Int32 SAL_CALL available( ) 101 throw(NotConnectedException, IOException, RuntimeException) 102 { 103 return m_seq.getLength() - nPos; 104 } 105 virtual void SAL_CALL closeInput( ) 106 throw(NotConnectedException, IOException, RuntimeException) 107 { 108 // not needed 109 } 110 sal_Int32 nPos; 111 Sequence< sal_Int8> m_seq; 112 }; 113 114 //------------------------------- 115 // Helper : create an input stream from a file 116 //------------------------------ 117 Reference< XInputStream > createStreamFromFile( 118 const char *pcFile ) 119 { 120 FILE *f = fopen( pcFile , "rb" ); 121 Reference< XInputStream > r; 122 123 if( f ) { 124 fseek( f , 0 , SEEK_END ); 125 int nLength = ftell( f ); 126 fseek( f , 0 , SEEK_SET ); 127 128 Sequence<sal_Int8> seqIn(nLength); 129 fread( seqIn.getArray() , nLength , 1 , f ); 130 131 r = Reference< XInputStream > ( new OInputStream( seqIn ) ); 132 fclose( f ); 133 } 134 return r; 135 } 136 137 //----------------------------------------- 138 // The document handler, which is needed for the saxparser 139 // The Documenthandler for reading sax 140 //----------------------------------------- 141 class TestDocumentHandler : 142 public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler > 143 { 144 public: 145 TestDocumentHandler( ) 146 { 147 } 148 149 public: // Error handler 150 virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException) 151 { 152 printf( "Error !\n" ); 153 throw SAXException( 154 OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) , 155 Reference < XInterface >() , 156 aSAXParseException ); 157 } 158 virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException) 159 { 160 printf( "Fatal Error !\n" ); 161 } 162 virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException) 163 { 164 printf( "Warning !\n" ); 165 } 166 167 168 public: // ExtendedDocumentHandler 169 170 virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException) 171 { 172 m_iElementCount = 0; 173 m_iAttributeCount = 0; 174 m_iWhitespaceCount =0; 175 m_iCharCount=0; 176 printf( "document started\n" ); 177 } 178 virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException) 179 { 180 printf( "document finished\n" ); 181 printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n", 182 m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount ); 183 184 } 185 virtual void SAL_CALL startElement(const OUString& aName, 186 const Reference< XAttributeList > & xAttribs) 187 throw (SAXException,RuntimeException) 188 { 189 m_iElementCount ++; 190 m_iAttributeCount += xAttribs->getLength(); 191 } 192 193 virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException) 194 { 195 // ignored 196 } 197 198 virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException) 199 { 200 m_iCharCount += aChars.getLength(); 201 } 202 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException) 203 { 204 m_iWhitespaceCount += aWhitespaces.getLength(); 205 } 206 207 virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException) 208 { 209 // ignored 210 } 211 212 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator) 213 throw (SAXException,RuntimeException) 214 { 215 // ignored 216 } 217 218 virtual InputSource SAL_CALL resolveEntity( 219 const OUString& sPublicId, 220 const OUString& sSystemId) 221 throw (SAXException,RuntimeException) 222 { 223 InputSource source; 224 source.sSystemId = sSystemId; 225 source.sPublicId = sPublicId; 226 227 source.aInputStream = createStreamFromFile( 228 OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) ); 229 230 return source; 231 } 232 233 virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException) 234 { 235 } 236 virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException) 237 { 238 } 239 virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException) 240 { 241 } 242 virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException) 243 { 244 } 245 246 virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException ) 247 { 248 249 } 250 251 public: 252 int m_iElementCount; 253 int m_iAttributeCount; 254 int m_iWhitespaceCount; 255 int m_iCharCount; 256 }; 257 258 //-------------------------------------- 259 // helper implementation for writing 260 // implements an XAttributeList 261 //------------------------------------- 262 struct AttributeListImpl_impl; 263 class AttributeListImpl : public WeakImplHelper1< XAttributeList > 264 { 265 public: 266 AttributeListImpl(); 267 AttributeListImpl( const AttributeListImpl & ); 268 ~AttributeListImpl(); 269 270 public: 271 virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException); 272 virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException); 273 virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException); 274 virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException); 275 virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException); 276 virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException); 277 278 public: 279 void addAttribute( const OUString &sName , 280 const OUString &sType , 281 const OUString &sValue ); 282 void clear(); 283 284 private: 285 struct AttributeListImpl_impl *m_pImpl; 286 }; 287 288 289 struct TagAttribute 290 { 291 TagAttribute(){} 292 TagAttribute( const OUString &sName, 293 const OUString &sType , 294 const OUString &sValue ) 295 { 296 this->sName = sName; 297 this->sType = sType; 298 this->sValue = sValue; 299 } 300 301 OUString sName; 302 OUString sType; 303 OUString sValue; 304 }; 305 306 struct AttributeListImpl_impl 307 { 308 AttributeListImpl_impl() 309 { 310 // performance improvement during adding 311 vecAttribute.reserve(20); 312 } 313 vector<struct TagAttribute> vecAttribute; 314 }; 315 316 317 318 sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException) 319 { 320 return m_pImpl->vecAttribute.size(); 321 } 322 323 324 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) 325 { 326 m_pImpl = new AttributeListImpl_impl; 327 *m_pImpl = *(r.m_pImpl); 328 } 329 330 OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException) 331 { 332 if( i < m_pImpl->vecAttribute.size() ) { 333 return m_pImpl->vecAttribute[i].sName; 334 } 335 return OUString(); 336 } 337 338 339 OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException) 340 { 341 if( i < m_pImpl->vecAttribute.size() ) { 342 return m_pImpl->vecAttribute[i].sType; 343 } 344 return OUString(); 345 } 346 347 OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException) 348 { 349 if( i < m_pImpl->vecAttribute.size() ) { 350 return m_pImpl->vecAttribute[i].sValue; 351 } 352 return OUString(); 353 354 } 355 356 OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException) 357 { 358 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); 359 360 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { 361 if( (*ii).sName == sName ) { 362 return (*ii).sType; 363 } 364 } 365 return OUString(); 366 } 367 368 OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException) 369 { 370 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin(); 371 372 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) { 373 if( (*ii).sName == sName ) { 374 return (*ii).sValue; 375 } 376 } 377 return OUString(); 378 } 379 380 381 382 AttributeListImpl::AttributeListImpl() 383 { 384 m_pImpl = new AttributeListImpl_impl; 385 } 386 387 388 389 AttributeListImpl::~AttributeListImpl() 390 { 391 delete m_pImpl; 392 } 393 394 395 void AttributeListImpl::addAttribute( const OUString &sName , 396 const OUString &sType , 397 const OUString &sValue ) 398 { 399 m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) ); 400 } 401 402 void AttributeListImpl::clear() 403 { 404 m_pImpl->vecAttribute.clear(); 405 } 406 407 408 //-------------------------------------- 409 // helper function for writing 410 // ensures that linebreaks are inserted 411 // when writing a long text. 412 // Note: this implementation may be a bit slow, 413 // but it shows, how the SAX-Writer handles the allowLineBreak calls. 414 //-------------------------------------- 415 void writeParagraphHelper( 416 const Reference< XExtendedDocumentHandler > &r , 417 const OUString & s) 418 { 419 int nMax = s.getLength(); 420 int nStart = 0; 421 422 Sequence<sal_uInt16> seq( s.getLength() ); 423 memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) ); 424 425 for( int n = 1 ; n < nMax ; n++ ){ 426 if( 32 == seq.getArray()[n] ) { 427 r->allowLineBreak(); 428 r->characters( s.copy( nStart , n - nStart ) ); 429 nStart = n; 430 } 431 } 432 r->allowLineBreak(); 433 r->characters( s.copy( nStart , n - nStart ) ); 434 } 435 436 437 //--------------------------------- 438 // helper implementation for SAX-Writer 439 // writes data to a file 440 //-------------------------------- 441 class OFileWriter : 442 public WeakImplHelper1< XOutputStream > 443 { 444 public: 445 OFileWriter( char *pcFile ) { strncpy( m_pcFile , pcFile, 256 - 1 ); m_f = 0; } 446 447 448 public: 449 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) 450 throw (NotConnectedException, BufferSizeExceededException, RuntimeException); 451 virtual void SAL_CALL flush(void) 452 throw (NotConnectedException, BufferSizeExceededException, RuntimeException); 453 virtual void SAL_CALL closeOutput(void) 454 throw (NotConnectedException, BufferSizeExceededException, RuntimeException); 455 private: 456 char m_pcFile[256]; 457 FILE *m_f; 458 }; 459 460 461 void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData) 462 throw (NotConnectedException, BufferSizeExceededException, RuntimeException) 463 { 464 if( ! m_f ) { 465 m_f = fopen( m_pcFile , "w" ); 466 } 467 468 fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f ); 469 } 470 471 472 void OFileWriter::flush(void) 473 throw (NotConnectedException, BufferSizeExceededException, RuntimeException) 474 { 475 fflush( m_f ); 476 } 477 478 void OFileWriter::closeOutput(void) 479 throw (NotConnectedException, BufferSizeExceededException, RuntimeException) 480 { 481 fclose( m_f ); 482 m_f = 0; 483 } 484 485 486 487 // Needed to switch on solaris threads 488 #ifdef SOLARIS 489 extern "C" void ChangeGlobalInit(); 490 #endif 491 int main (int argc, char **argv) 492 { 493 494 if( argc < 3) { 495 printf( "usage : saxdemo inputfile outputfile\n" ); 496 exit( 0 ); 497 } 498 #ifdef SOLARIS 499 // switch on threads in solaris 500 ChangeGlobalInit(); 501 #endif 502 503 // create service manager 504 Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory( 505 OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" )) ); 506 507 Reference < XImplementationRegistration > xReg; 508 try 509 { 510 // Create registration service 511 Reference < XInterface > x = xSMgr->createInstance( 512 OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) ); 513 xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY ); 514 } 515 catch( Exception & ) { 516 printf( "Couldn't create ImplementationRegistration service\n" ); 517 exit(1); 518 } 519 520 OString sTestName; 521 try 522 { 523 // Load dll for the tested component 524 OUString aDllName = 525 OUString::createFromAscii( "sax.uno" SAL_DLLEXTENSION ); 526 xReg->registerImplementation( 527 OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ), 528 aDllName, 529 Reference< XSimpleRegistry > () ); 530 } 531 catch( Exception &e ) { 532 printf( "Couldn't reach sax dll\n" ); 533 printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() ); 534 535 exit(1); 536 } 537 538 539 //-------------------------------- 540 // parser demo 541 // read xml from a file and count elements 542 //-------------------------------- 543 Reference< XInterface > x = xSMgr->createInstance( 544 OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) ); 545 if( x.is() ) 546 { 547 Reference< XParser > rParser( x , UNO_QUERY ); 548 549 // create and connect the document handler to the parser 550 TestDocumentHandler *pDocHandler = new TestDocumentHandler( ); 551 552 Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler ); 553 Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler ); 554 555 rParser->setDocumentHandler( rDocHandler ); 556 rParser->setEntityResolver( rEntityResolver ); 557 558 // create the input stream 559 InputSource source; 560 source.aInputStream = createStreamFromFile( argv[1] ); 561 source.sSystemId = OUString::createFromAscii( argv[1] ); 562 563 try 564 { 565 // start parsing 566 rParser->parseStream( source ); 567 } 568 569 catch( Exception & e ) 570 { 571 OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 ); 572 printf( "Exception during parsing : %s\n" , o1.getStr() ); 573 } 574 } 575 else 576 { 577 printf( "couln't create sax-parser component\n" ); 578 } 579 580 581 //---------------------- 582 // The SAX-Writer demo 583 //---------------------- 584 x= xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ); 585 if( x.is() ) 586 { 587 printf( "start writing to %s\n" , argv[2] ); 588 589 OFileWriter *pw = new OFileWriter( argv[2] ); 590 Reference< XActiveDataSource > source( x , UNO_QUERY ); 591 source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) ); 592 593 AttributeListImpl *pList = new AttributeListImpl; 594 Reference< XAttributeList > rList( (XAttributeList *) pList ); 595 596 Reference< XExtendedDocumentHandler > r( x , UNO_QUERY ); 597 r->startDocument(); 598 599 pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )), 600 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , 601 OUString( RTL_CONSTASCII_USTRINGPARAM("foo\n u")) ); 602 pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) , 603 OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) , 604 OUString( RTL_CONSTASCII_USTRINGPARAM("foo2")) ); 605 606 r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList ); 607 // tells the writer to insert a linefeed 608 r->ignorableWhitespace( OUString() ); 609 610 r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) ); 611 r->ignorableWhitespace( OUString() ); 612 613 r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList ); 614 r->ignorableWhitespace( OUString() ); 615 616 // the enpassant must be converted & -> & 617 r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("ü")) ); 618 r->ignorableWhitespace( OUString() ); 619 620 // '>' must not be converted 621 r->startCDATA(); 622 r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(" > foo < ")) ); 623 r->endCDATA(); 624 r->ignorableWhitespace( OUString() ); 625 626 OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM( 627 "This is only a test to check, if the writer inserts line feeds " 628 "if needed or if the writer puts the whole text into one line." )); 629 writeParagraphHelper( r , testParagraph ); 630 631 r->ignorableWhitespace( OUString() ); 632 r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("This is a comment !")) ); 633 r->ignorableWhitespace( OUString() ); 634 635 r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList ); 636 r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) ); 637 r->ignorableWhitespace( OUString() ); 638 639 r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) ); 640 r->ignorableWhitespace( OUString() ); 641 642 r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) ); 643 r->endDocument(); 644 645 printf( "finished writing\n" ); 646 } 647 else 648 { 649 printf( "couln't create sax-writer component\n" ); 650 } 651 } 652