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:
OInputStream(const Sequence<sal_Int8> & seq)68 OInputStream( const Sequence< sal_Int8 >&seq ) :
69 m_seq( seq ),
70 nPos( 0 )
71 {}
72
73 public:
readBytes(Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)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 }
readSomeBytes(::com::sun::star::uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)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 }
skipBytes(sal_Int32 nBytesToSkip)91 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
92 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
93 {
94 // not implemented
95 }
available()96 virtual sal_Int32 SAL_CALL available( )
97 throw(NotConnectedException, IOException, RuntimeException)
98 {
99 return m_seq.getLength() - nPos;
100 }
closeInput()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 //------------------------------
createStreamFromFile(const char * pcFile)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:
TestDocumentHandler()141 TestDocumentHandler( )
142 {
143 }
144
145 public: // Error handler
error(const Any & aSAXParseException)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 }
fatalError(const Any & aSAXParseException)154 virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException)
155 {
156 printf( "Fatal Error !\n" );
157 }
warning(const Any & aSAXParseException)158 virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException)
159 {
160 printf( "Warning !\n" );
161 }
162
163
164 public: // ExtendedDocumentHandler
165
startDocument(void)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 }
endDocument(void)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 }
startElement(const OUString & aName,const Reference<XAttributeList> & xAttribs)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
endElement(const OUString & aName)189 virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException)
190 {
191 // ignored
192 }
193
characters(const OUString & aChars)194 virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
195 {
196 m_iCharCount += aChars.getLength();
197 }
ignorableWhitespace(const OUString & aWhitespaces)198 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
199 {
200 m_iWhitespaceCount += aWhitespaces.getLength();
201 }
202
processingInstruction(const OUString & aTarget,const OUString & aData)203 virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException)
204 {
205 // ignored
206 }
207
setDocumentLocator(const Reference<XLocator> & xLocator)208 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator)
209 throw (SAXException,RuntimeException)
210 {
211 // ignored
212 }
213
resolveEntity(const OUString & sPublicId,const OUString & sSystemId)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
startCDATA(void)229 virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
230 {
231 }
endCDATA(void)232 virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException)
233 {
234 }
comment(const OUString & sComment)235 virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException)
236 {
237 }
unknown(const OUString & sString)238 virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException)
239 {
240 }
241
allowLineBreak(void)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 {
TagAttributeTagAttribute287 TagAttribute(){}
TagAttributeTagAttribute288 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 {
AttributeListImpl_implAttributeListImpl_impl304 AttributeListImpl_impl()
305 {
306 // performance improvement during adding
307 vecAttribute.reserve(20);
308 }
309 vector<struct TagAttribute> vecAttribute;
310 };
311
312
313
getLength(void)314 sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException)
315 {
316 return m_pImpl->vecAttribute.size();
317 }
318
319
AttributeListImpl(const AttributeListImpl & r)320 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
321 {
322 m_pImpl = new AttributeListImpl_impl;
323 *m_pImpl = *(r.m_pImpl);
324 }
325
getNameByIndex(sal_Int16 i)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
getTypeByIndex(sal_Int16 i)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
getValueByIndex(sal_Int16 i)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
getTypeByName(const OUString & sName)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
getValueByName(const OUString & sName)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
AttributeListImpl()378 AttributeListImpl::AttributeListImpl()
379 {
380 m_pImpl = new AttributeListImpl_impl;
381 }
382
383
384
~AttributeListImpl()385 AttributeListImpl::~AttributeListImpl()
386 {
387 delete m_pImpl;
388 }
389
390
addAttribute(const OUString & sName,const OUString & sType,const OUString & sValue)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
clear()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 //--------------------------------------
writeParagraphHelper(const Reference<XExtendedDocumentHandler> & r,const OUString & s)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:
OFileWriter(char * pcFile)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
writeBytes(const Sequence<sal_Int8> & aData)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
flush(void)468 void OFileWriter::flush(void)
469 throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
470 {
471 fflush( m_f );
472 }
473
closeOutput(void)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
main(int argc,char ** argv)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