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