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