xref: /trunk/main/sax/source/expatwrap/sax_expat.cxx (revision 45c5a00162811bd03b87fcb4fe9996782f2b59ec)
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 #include <stdlib.h>
24 #include <string.h>
25 #include <sal/alloca.h>
26 #include <vector>
27 
28 #include <osl/diagnose.h>
29 
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/util/XCloneable.hpp>
32 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/sax/SAXParseException.hpp>
35 #include <com/sun/star/io/XSeekable.hpp>
36 
37 #include <cppuhelper/factory.hxx>
38 #include <cppuhelper/weak.hxx>
39 #include <cppuhelper/implbase1.hxx>
40 #include <cppuhelper/implbase2.hxx>
41 #include <cppuhelper/implementationentry.hxx>
42 
43 #include <expat.h>
44 
45 using namespace ::rtl;
46 using namespace ::std;
47 using namespace ::osl;
48 using namespace ::cppu;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::registry;
52 using namespace ::com::sun::star::xml::sax;
53 using namespace ::com::sun::star::util;
54 using namespace ::com::sun::star::io;
55 
56 #include "factory.hxx"
57 #include "attrlistimpl.hxx"
58 #include "xml2utf.hxx"
59 
60 namespace sax_expatwrap {
61 
62 // Useful macros for correct String conversion depending on the chosen expat-mode
63 #ifdef XML_UNICODE
64 OUString XmlNChar2OUString( const XML_Char *p , int nLen )
65 {
66     if( p ) {
67         if( sizeof( sal_Unicode ) == sizeof( XML_Char ) )
68         {
69             return OUString( (sal_Unicode*)p,nLen);
70         }
71         else
72         {
73             sal_Unicode *pWchar = (sal_Unicode *)alloca( sizeof( sal_Unicode ) * nLen );
74             for( int n = 0 ; n < nLen ; n++ ) {
75                 pWchar[n] = (sal_Unicode) p[n];
76             }
77             return OUString( pWchar , nLen );
78         }
79     }
80     else {
81         return OUString();
82     }
83 }
84 
85 OUString XmlChar2OUString( const XML_Char *p )
86 {
87     if( p ) {
88         int nLen;
89         for( nLen = 0 ; p[nLen] ; nLen ++ )
90             ;
91         return XmlNChar2OUString( p , nLen );
92      }
93      else return OUString();
94 }
95 
96 
97 #define XML_CHAR_TO_OUSTRING(x) XmlChar2OUString(x)
98 #define XML_CHAR_N_TO_USTRING(x,n) XmlNChar2OUString(x,n)
99 #else
100 #define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
101 #define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
102 #endif
103 
104 
105 /*
106 * The following macro encapsulates any call to an event handler.
107 * It ensures, that exceptions thrown by the event handler are
108 * treated properly.
109 */
110 #define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
111     if( ! pThis->bExceptionWasThrown ) { \
112         try {\
113             pThis->call;\
114         }\
115         catch( SAXParseException &e ) {\
116             pThis->callErrorHandler( pThis ,  e );\
117         }\
118         catch( SAXException &e ) {\
119             pThis->callErrorHandler( pThis , SAXParseException(\
120                                             e.Message, \
121                                             e.Context, \
122                                             e.WrappedException,\
123                                             pThis->rDocumentLocator->getPublicId(),\
124                                             pThis->rDocumentLocator->getSystemId(),\
125                                             pThis->rDocumentLocator->getLineNumber(),\
126                                             pThis->rDocumentLocator->getColumnNumber()\
127                                      ) );\
128         }\
129         catch( com::sun::star::uno::RuntimeException &e ) {\
130             pThis->bExceptionWasThrown = sal_True; \
131             pThis->bRTExceptionWasThrown = sal_True; \
132             pImpl->rtexception = e; \
133         }\
134     }\
135     ((void)0)
136 
137 
138 class SaxExpatParser_Impl;
139 
140 
141 // This class implements the external Parser interface
142 class SaxExpatParser :
143     public WeakImplHelper2<
144                 XParser,
145                 XServiceInfo
146                           >
147 {
148 
149 public:
150     SaxExpatParser();
151     ~SaxExpatParser();
152 
153 public:
154 
155     // The implementation details
156     static OUString                 getImplementationName_Static(void) throw();
157     static Sequence< OUString >     getSupportedServiceNames_Static(void) throw ();
158 
159 public:
160     // The SAX-Parser-Interface
161     virtual void SAL_CALL parseStream(  const InputSource& structSource);
162     virtual void SAL_CALL setDocumentHandler(const Reference< XDocumentHandler > & xHandler);
163 
164     virtual void SAL_CALL setErrorHandler(const Reference< XErrorHandler > & xHandler);
165     virtual void SAL_CALL setDTDHandler(const Reference < XDTDHandler > & xHandler);
166     virtual void SAL_CALL setEntityResolver(const Reference<  XEntityResolver >& xResolver);
167 
168     virtual void SAL_CALL setLocale( const Locale &locale );
169 
170 public: // XServiceInfo
171     OUString                     SAL_CALL getImplementationName() throw ();
172     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
173     sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) throw ();
174 
175 private:
176 
177     SaxExpatParser_Impl         *m_pImpl;
178 
179 };
180 
181 //--------------------------------------
182 // the extern interface
183 //---------------------------------------
184 Reference< XInterface > SAL_CALL SaxExpatParser_CreateInstance(
185     Reference< XComponentContext > const & )
186 {
187     SaxExpatParser *p = new SaxExpatParser;
188 
189     return Reference< XInterface > ( (OWeakObject * ) p );
190 }
191 
192 OUString SaxExpatParser::getImplementationName_Static() throw ()
193 {
194     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.xml.sax.ParserExpat" ) );
195 }
196 
197 Sequence< OUString >    SaxExpatParser::getSupportedServiceNames_Static(void) throw ()
198 {
199     Sequence<OUString> aRet(1);
200     aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser" ) );
201     return aRet;
202 }
203 
204 
205 //---------------------------------------------
206 // the implementation part
207 //---------------------------------------------
208 
209 
210 // Entity binds all information neede for a single file
211 struct Entity
212 {
213     InputSource         structSource;
214     XML_Parser          pParser;
215     XMLFile2UTFConverter converter;
216 };
217 
218 
219 class SaxExpatParser_Impl
220 {
221 public: // module scope
222     Mutex               aMutex;
223 
224     Reference< XDocumentHandler >   rDocumentHandler;
225     Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
226 
227     Reference< XErrorHandler >  rErrorHandler;
228     Reference< XDTDHandler >    rDTDHandler;
229     Reference< XEntityResolver > rEntityResolver;
230     Reference < XLocator >      rDocumentLocator;
231 
232 
233     Reference < XAttributeList >    rAttrList;
234     AttributeList   *pAttrList;
235 
236     // External entity stack
237     vector<struct Entity>   vecEntity;
238     void pushEntity( const struct Entity &entity )
239         { vecEntity.push_back( entity ); }
240     void popEntity()
241         { vecEntity.pop_back( ); }
242     struct Entity &getEntity()
243         { return vecEntity.back(); }
244 
245 
246     // Exception cannot be thrown through the C-XmlParser (possible resource leaks),
247     // therefor the exception must be saved somewhere.
248     SAXParseException   exception;
249     RuntimeException    rtexception;
250     sal_Bool            bExceptionWasThrown;
251     sal_Bool            bRTExceptionWasThrown;
252 
253     Locale              locale;
254 
255 public:
256     // the C-Callbacks for the expat parser
257     void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
258     void static callbackEndElement(void *userData, const XML_Char *name);
259     void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
260     void static callbackProcessingInstruction(  void *userData ,
261                                                 const XML_Char *sTarget ,
262                                                 const XML_Char *sData );
263 
264     void static callbackUnparsedEntityDecl( void *userData ,
265                                             const XML_Char *entityName,
266                                             const XML_Char *base,
267                                             const XML_Char *systemId,
268                                             const XML_Char *publicId,
269                                             const XML_Char *notationName);
270 
271     void static callbackNotationDecl(   void *userData,
272                                         const XML_Char *notationName,
273                                         const XML_Char *base,
274                                         const XML_Char *systemId,
275                                         const XML_Char *publicId);
276 
277     int static callbackExternalEntityRef(   XML_Parser parser,
278                                             const XML_Char *openEntityNames,
279                                             const XML_Char *base,
280                                             const XML_Char *systemId,
281                                             const XML_Char *publicId);
282 
283     int static callbackUnknownEncoding(void *encodingHandlerData,
284                                                 const XML_Char *name,
285                                                 XML_Encoding *info);
286 
287     void static callbackDefault( void *userData,  const XML_Char *s,  int len);
288 
289     void static callbackStartCDATA( void *userData );
290     void static callbackEndCDATA( void *userData );
291     void static callbackComment( void *userData , const XML_Char *s );
292     void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
293 
294 public:
295     void parse();
296 };
297 
298 extern "C"
299 {
300     static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
301     {
302         SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
303     }
304     static void call_callbackEndElement(void *userData, const XML_Char *name)
305     {
306         SaxExpatParser_Impl::callbackEndElement(userData,name);
307     }
308     static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
309     {
310         SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
311     }
312     static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
313     {
314         SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
315     }
316     static void call_callbackUnparsedEntityDecl(void *userData ,
317                                                 const XML_Char *entityName,
318                                                 const XML_Char *base,
319                                                 const XML_Char *systemId,
320                                                 const XML_Char *publicId,
321                                                 const XML_Char *notationName)
322     {
323         SaxExpatParser_Impl::callbackUnparsedEntityDecl(userData,entityName,base,systemId,publicId,notationName);
324     }
325     static void call_callbackNotationDecl(void *userData,
326                                           const XML_Char *notationName,
327                                           const XML_Char *base,
328                                           const XML_Char *systemId,
329                                           const XML_Char *publicId)
330     {
331         SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
332     }
333     static int call_callbackExternalEntityRef(XML_Parser parser,
334                                               const XML_Char *openEntityNames,
335                                               const XML_Char *base,
336                                               const XML_Char *systemId,
337                                               const XML_Char *publicId)
338     {
339         return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
340     }
341     static int call_callbackUnknownEncoding(void *encodingHandlerData,
342                                             const XML_Char *name,
343                                             XML_Encoding *info)
344     {
345         return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
346     }
347     static void call_callbackDefault( void *userData,  const XML_Char *s,  int len)
348     {
349         SaxExpatParser_Impl::callbackDefault(userData,s,len);
350     }
351     static void call_callbackStartCDATA( void *userData )
352     {
353         SaxExpatParser_Impl::callbackStartCDATA(userData);
354     }
355     static void call_callbackEndCDATA( void *userData )
356     {
357         SaxExpatParser_Impl::callbackEndCDATA(userData);
358     }
359     static void call_callbackComment( void *userData , const XML_Char *s )
360     {
361         SaxExpatParser_Impl::callbackComment(userData,s);
362     }
363 }
364 
365 
366 //---------------------------------------------
367 // LocatorImpl
368 //---------------------------------------------
369 class LocatorImpl :
370     public WeakImplHelper2< XLocator, com::sun::star::io::XSeekable >
371     // should use a different interface for stream positions!
372 {
373 public:
374     LocatorImpl( SaxExpatParser_Impl *p )
375     {
376         m_pParser    = p;
377     }
378 
379 public: //XLocator
380     virtual sal_Int32 SAL_CALL getColumnNumber(void) throw ()
381     {
382         return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
383     }
384     virtual sal_Int32 SAL_CALL getLineNumber(void) throw ()
385     {
386         return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
387     }
388     virtual OUString SAL_CALL getPublicId(void) throw ()
389     {
390         return m_pParser->getEntity().structSource.sPublicId;
391     }
392     virtual OUString SAL_CALL getSystemId(void) throw ()
393     {
394         return m_pParser->getEntity().structSource.sSystemId;
395     }
396 
397     // XSeekable (only for getPosition)
398 
399     virtual void SAL_CALL seek( sal_Int64 ) throw()
400     {
401     }
402     virtual sal_Int64 SAL_CALL getPosition() throw()
403     {
404         return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
405     }
406     virtual ::sal_Int64 SAL_CALL getLength() throw()
407     {
408         return 0;
409     }
410 
411 private:
412 
413     SaxExpatParser_Impl *m_pParser;
414 };
415 
416 
417 
418 
419 SaxExpatParser::SaxExpatParser(  )
420 {
421     m_pImpl = new SaxExpatParser_Impl;
422 
423     LocatorImpl *pLoc = new LocatorImpl( m_pImpl );
424     m_pImpl->rDocumentLocator = Reference< XLocator > ( pLoc );
425 
426     // performance-Improvment. Reference is needed when calling the startTag callback.
427     // Handing out the same object with every call is allowed (see sax-specification)
428     m_pImpl->pAttrList = new AttributeList;
429     m_pImpl->rAttrList = Reference< XAttributeList > ( m_pImpl->pAttrList );
430 
431     m_pImpl->bExceptionWasThrown = sal_False;
432     m_pImpl->bRTExceptionWasThrown = sal_False;
433 }
434 
435 SaxExpatParser::~SaxExpatParser()
436 {
437     delete m_pImpl;
438 }
439 
440 
441 /***************
442 *
443 * parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
444 * the file-specific initialization work. (During a parser run, external files may be opened)
445 *
446 ****************/
447 void SaxExpatParser::parseStream(   const InputSource& structSource)
448 {
449     // Only one text at one time
450     MutexGuard guard( m_pImpl->aMutex );
451 
452 
453     struct Entity entity;
454     entity.structSource = structSource;
455 
456     if( ! entity.structSource.aInputStream.is() )
457     {
458         throw SAXException( OUString::createFromAscii( "No input source" ) ,
459                             Reference< XInterface > () , Any() );
460     }
461 
462     entity.converter.setInputStream( entity.structSource.aInputStream );
463     if( entity.structSource.sEncoding.getLength() )
464     {
465         entity.converter.setEncoding(
466             OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
467     }
468 
469     // create parser with proper encoding
470     entity.pParser = XML_ParserCreate( 0 );
471     if( ! entity.pParser )
472     {
473         throw SAXException( OUString::createFromAscii( "Couldn't create parser" ) ,
474                             Reference< XInterface > (), Any() );
475     }
476 
477     // set all necessary C-Callbacks
478     XML_SetUserData( entity.pParser , m_pImpl );
479     XML_SetElementHandler(  entity.pParser ,
480                             call_callbackStartElement ,
481                             call_callbackEndElement );
482     XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
483     XML_SetProcessingInstructionHandler(entity.pParser ,
484                                         call_callbackProcessingInstruction );
485     XML_SetUnparsedEntityDeclHandler(   entity.pParser,
486                                         call_callbackUnparsedEntityDecl );
487     XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
488     XML_SetExternalEntityRefHandler(    entity.pParser,
489                                         call_callbackExternalEntityRef);
490     XML_SetUnknownEncodingHandler( entity.pParser,  call_callbackUnknownEncoding ,0);
491 
492     if( m_pImpl->rExtendedDocumentHandler.is() ) {
493 
494         // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
495         // given, these callbacks can be ignored
496         XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
497         XML_SetCommentHandler( entity.pParser, call_callbackComment );
498         XML_SetCdataSectionHandler(     entity.pParser ,
499                                         call_callbackStartCDATA ,
500                                         call_callbackEndCDATA );
501     }
502 
503 
504     m_pImpl->exception = SAXParseException();
505     m_pImpl->pushEntity( entity );
506     try
507     {
508         // start the document
509         if( m_pImpl->rDocumentHandler.is() ) {
510             m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
511             m_pImpl->rDocumentHandler->startDocument();
512         }
513 
514         m_pImpl->parse();
515 
516         // finish document
517         if( m_pImpl->rDocumentHandler.is() ) {
518             m_pImpl->rDocumentHandler->endDocument();
519         }
520     }
521 //      catch( SAXParseException &e )
522 //  {
523 //      m_pImpl->popEntity();
524 //          XML_ParserFree( entity.pParser );
525 //        Any aAny;
526 //        aAny <<= e;
527 //          throw SAXException( e.Message, e.Context, aAny );
528 //      }
529     catch( SAXException & )
530     {
531         m_pImpl->popEntity();
532         XML_ParserFree( entity.pParser );
533         throw;
534     }
535     catch( IOException & )
536     {
537         m_pImpl->popEntity();
538         XML_ParserFree( entity.pParser );
539         throw;
540     }
541     catch( RuntimeException & )
542     {
543         m_pImpl->popEntity();
544         XML_ParserFree( entity.pParser );
545         throw;
546     }
547 
548     m_pImpl->popEntity();
549     XML_ParserFree( entity.pParser );
550 }
551 
552 void SaxExpatParser::setDocumentHandler(const Reference< XDocumentHandler > & xHandler)
553 {
554     m_pImpl->rDocumentHandler = xHandler;
555     m_pImpl->rExtendedDocumentHandler =
556         Reference< XExtendedDocumentHandler >( xHandler , UNO_QUERY );
557 }
558 
559 void SaxExpatParser::setErrorHandler(const Reference< XErrorHandler > & xHandler)
560 {
561     m_pImpl->rErrorHandler = xHandler;
562 }
563 
564 void SaxExpatParser::setDTDHandler(const Reference< XDTDHandler > & xHandler)
565 {
566     m_pImpl->rDTDHandler = xHandler;
567 }
568 
569 void SaxExpatParser::setEntityResolver(const Reference < XEntityResolver > & xResolver)
570 {
571     m_pImpl->rEntityResolver = xResolver;
572 }
573 
574 
575 void SaxExpatParser::setLocale( const Locale & locale )
576 {
577     m_pImpl->locale = locale;
578 }
579 
580 // XServiceInfo
581 OUString SaxExpatParser::getImplementationName() throw ()
582 {
583     return getImplementationName_Static();
584 }
585 
586 // XServiceInfo
587 sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw ()
588 {
589     Sequence< OUString > aSNL = getSupportedServiceNames();
590     const OUString * pArray = aSNL.getConstArray();
591 
592     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
593         if( pArray[i] == ServiceName )
594             return sal_True;
595 
596     return sal_False;
597 }
598 
599 // XServiceInfo
600 Sequence< OUString > SaxExpatParser::getSupportedServiceNames(void) throw ()
601 {
602     return getSupportedServiceNames_Static();
603 }
604 
605 
606 /*---------------------------------------
607 *
608 * Helper functions and classes
609 *
610 *
611 *-------------------------------------------*/
612 OUString getErrorMessage( XML_Error xmlE, OUString sSystemId , sal_Int32 nLine )
613 {
614     OUString Message;
615     if( XML_ERROR_NONE == xmlE ) {
616         Message = OUString::createFromAscii( "No" );
617     }
618     else if( XML_ERROR_NO_MEMORY == xmlE ) {
619         Message = OUString::createFromAscii( "no memory" );
620     }
621     else if( XML_ERROR_SYNTAX == xmlE ) {
622         Message = OUString::createFromAscii( "syntax" );
623     }
624     else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
625         Message = OUString::createFromAscii( "no elements" );
626     }
627     else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
628         Message = OUString::createFromAscii( "invalid token" );
629     }
630     else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
631         Message = OUString::createFromAscii( "unclosed token" );
632     }
633     else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
634         Message = OUString::createFromAscii( "partial char" );
635     }
636     else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
637         Message = OUString::createFromAscii( "tag mismatch" );
638     }
639     else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
640         Message = OUString::createFromAscii( "duplicate attribute" );
641     }
642     else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
643         Message = OUString::createFromAscii( "junk after doc element" );
644     }
645     else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
646         Message = OUString::createFromAscii( "parameter entity reference" );
647     }
648     else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
649         Message = OUString::createFromAscii( "undefined entity" );
650     }
651     else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
652         Message = OUString::createFromAscii( "recursive entity reference" );
653     }
654     else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
655         Message = OUString::createFromAscii( "async entity" );
656     }
657     else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
658         Message = OUString::createFromAscii( "bad char reference" );
659     }
660     else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
661         Message = OUString::createFromAscii( "binary entity reference" );
662     }
663     else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
664         Message = OUString::createFromAscii( "attribute external entity reference" );
665     }
666     else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
667         Message = OUString::createFromAscii( "misplaced xml processing instruction" );
668     }
669     else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
670         Message = OUString::createFromAscii( "unknown encoding" );
671     }
672     else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
673         Message = OUString::createFromAscii( "incorrect encoding" );
674     }
675     else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
676         Message = OUString::createFromAscii( "unclosed cdata section" );
677     }
678     else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
679         Message = OUString::createFromAscii( "external entity reference" );
680     }
681     else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
682         Message = OUString::createFromAscii( "not standalone" );
683     }
684 
685     OUString str = OUString::createFromAscii( "[" );
686     str += sSystemId;
687     str += OUString::createFromAscii( " line " );
688     str += OUString::valueOf( nLine );
689     str += OUString::createFromAscii( "]: " );
690     str += Message;
691     str += OUString::createFromAscii( "error" );
692 
693     return str;
694 }
695 
696 
697 // starts parsing with actual parser !
698 void SaxExpatParser_Impl::parse( )
699 {
700     const int nBufSize = 16*1024;
701 
702     int nRead   = nBufSize;
703     Sequence< sal_Int8 > seqOut(nBufSize);
704 
705     while( nRead ) {
706         nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
707 
708         if( ! nRead ) {
709             XML_Parse( getEntity().pParser ,
710                                    ( const char * ) seqOut.getArray() ,
711                                    0 ,
712                                    1 );
713             break;
714         }
715 
716         sal_Bool bContinue = ( XML_Parse( getEntity().pParser ,
717                                                 (const char *) seqOut.getArray(),
718                                                 nRead,
719                                                 0 ) != 0 );
720 
721         if( ! bContinue || this->bExceptionWasThrown ) {
722 
723             if ( this->bRTExceptionWasThrown )
724                 throw rtexception;
725 
726             // Error during parsing !
727             XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
728             OUString sSystemId = rDocumentLocator->getSystemId();
729             sal_Int32 nLine = rDocumentLocator->getLineNumber();
730 
731             SAXParseException aExcept(
732                 getErrorMessage(xmlE , sSystemId, nLine) ,
733                 Reference< XInterface >(),
734                 Any( &exception , getCppuType( &exception) ),
735                 rDocumentLocator->getPublicId(),
736                 rDocumentLocator->getSystemId(),
737                 rDocumentLocator->getLineNumber(),
738                 rDocumentLocator->getColumnNumber()
739                 );
740 
741             if( rErrorHandler.is() ) {
742 
743                 // error handler is set, so the handler may throw the exception
744                 Any a;
745                 a <<= aExcept;
746                 rErrorHandler->fatalError( a );
747             }
748 
749             // Error handler has not thrown an exception, but parsing cannot go on,
750             // so an exception MUST be thrown.
751             throw aExcept;
752         } // if( ! bContinue )
753     } // while
754 }
755 
756 //------------------------------------------
757 //
758 // The C-Callbacks
759 //
760 //-----------------------------------------
761 void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
762                                                 const XML_Char *pwName ,
763                                                 const XML_Char **awAttributes )
764 {
765     // in case of two concurrent threads, there is only the danger of an leak,
766     // which is neglectable for one string
767     static OUString g_CDATA( RTL_CONSTASCII_USTRINGPARAM( "CDATA" ) );
768 
769     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
770 
771     if( pImpl->rDocumentHandler.is() ) {
772 
773         int i = 0;
774         pImpl->pAttrList->clear();
775 
776         while( awAttributes[i] ) {
777             OSL_ASSERT( awAttributes[i+1] );
778             pImpl->pAttrList->addAttribute(
779                 XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
780                 g_CDATA ,  // expat doesn't know types
781                 XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
782             i +=2;
783         }
784 
785         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
786             pImpl ,
787             rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
788                                             pImpl->rAttrList ) );
789     }
790 }
791 
792 void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName  )
793 {
794     SaxExpatParser_Impl  *pImpl = ((SaxExpatParser_Impl*)pvThis);
795 
796     if( pImpl->rDocumentHandler.is() ) {
797         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
798                 rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
799     }
800 }
801 
802 
803 void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
804 {
805     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
806 
807     if( pImpl->rDocumentHandler.is() ) {
808         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
809                 rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
810     }
811 }
812 
813 void SaxExpatParser_Impl::callbackProcessingInstruction(    void *pvThis,
814                                                     const XML_Char *sTarget ,
815                                                     const XML_Char *sData )
816 {
817     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
818     if( pImpl->rDocumentHandler.is() ) {
819         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
820                     pImpl ,
821                     rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
822                     XML_CHAR_TO_OUSTRING( sData ) ) );
823     }
824 }
825 
826 
827 void SaxExpatParser_Impl::callbackUnparsedEntityDecl(void *pvThis ,
828                                                      const XML_Char *entityName,
829                                                      const XML_Char * /*base*/,
830                                                      const XML_Char *systemId,
831                                                      const XML_Char *publicId,
832                                                      const XML_Char *notationName)
833 {
834     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
835     if( pImpl->rDTDHandler.is() ) {
836         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
837             pImpl ,
838             rDTDHandler->unparsedEntityDecl(
839                 XML_CHAR_TO_OUSTRING( entityName ),
840                 XML_CHAR_TO_OUSTRING( publicId ) ,
841                 XML_CHAR_TO_OUSTRING( systemId ) ,
842                 XML_CHAR_TO_OUSTRING( notationName ) ) );
843     }
844 }
845 
846 void SaxExpatParser_Impl::callbackNotationDecl( void *pvThis,
847                                                 const XML_Char *notationName,
848                                                 const XML_Char * /*base*/,
849                                                 const XML_Char *systemId,
850                                                 const XML_Char *publicId)
851 {
852     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
853     if( pImpl->rDTDHandler.is() ) {
854         CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
855                 rDTDHandler->notationDecl(  XML_CHAR_TO_OUSTRING( notationName ) ,
856                                             XML_CHAR_TO_OUSTRING( publicId ) ,
857                                             XML_CHAR_TO_OUSTRING( systemId ) ) );
858     }
859 
860 }
861 
862 
863 
864 int SaxExpatParser_Impl::callbackExternalEntityRef( XML_Parser parser,
865                                                     const XML_Char *context,
866                                                     const XML_Char * /*base*/,
867                                                     const XML_Char *systemId,
868                                                     const XML_Char *publicId)
869 {
870     sal_Bool bOK = sal_True;
871     InputSource source;
872     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)XML_GetUserData( parser ));
873 
874     struct Entity entity;
875 
876     if( pImpl->rEntityResolver.is() ) {
877         try
878         {
879             entity.structSource = pImpl->rEntityResolver->resolveEntity(
880                 XML_CHAR_TO_OUSTRING( publicId ) ,
881                 XML_CHAR_TO_OUSTRING( systemId ) );
882         }
883         catch( SAXParseException & e )
884         {
885             pImpl->exception = e;
886             bOK = sal_False;
887         }
888         catch( SAXException & e )
889         {
890             pImpl->exception = SAXParseException(
891                 e.Message , e.Context , e.WrappedException ,
892                 pImpl->rDocumentLocator->getPublicId(),
893                 pImpl->rDocumentLocator->getSystemId(),
894                 pImpl->rDocumentLocator->getLineNumber(),
895                 pImpl->rDocumentLocator->getColumnNumber() );
896             bOK = sal_False;
897         }
898     }
899 
900     if( entity.structSource.aInputStream.is() ) {
901         entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 );
902         if( ! entity.pParser )
903         {
904             return sal_False;
905         }
906 
907         entity.converter.setInputStream( entity.structSource.aInputStream );
908         pImpl->pushEntity( entity );
909         try
910         {
911             pImpl->parse();
912         }
913         catch( SAXParseException & e )
914         {
915             pImpl->exception = e;
916             bOK = sal_False;
917         }
918         catch( IOException &e )
919         {
920             pImpl->exception.WrappedException <<= e;
921             bOK = sal_False;
922         }
923         catch( RuntimeException &e )
924         {
925             pImpl->exception.WrappedException <<=e;
926             bOK = sal_False;
927         }
928 
929         pImpl->popEntity();
930 
931         XML_ParserFree( entity.pParser );
932     }
933 
934     return bOK;
935 }
936 
937 int SaxExpatParser_Impl::callbackUnknownEncoding(void * /*encodingHandlerData*/,
938                                                  const XML_Char * /*name*/,
939                                                  XML_Encoding * /*info*/)
940 {
941     return 0;
942 }
943 
944 void SaxExpatParser_Impl::callbackDefault( void *pvThis,  const XML_Char *s,  int len)
945 {
946     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
947 
948     CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(  pImpl,
949                 rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
950 }
951 
952 void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
953 {
954     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
955     CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
956                 rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
957 }
958 
959 void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
960 {
961     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
962 
963     CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
964 }
965 
966 
967 void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
968                                             const SAXParseException & e )
969 {
970     try
971     {
972         if( pImpl->rErrorHandler.is() ) {
973             Any a;
974             a <<= e;
975             pImpl->rErrorHandler->error( a );
976         }
977         else {
978             pImpl->exception = e;
979             pImpl->bExceptionWasThrown = sal_True;
980         }
981     }
982     catch( SAXParseException & ex ) {
983         pImpl->exception = ex;
984         pImpl->bExceptionWasThrown = sal_True;
985     }
986     catch( SAXException & ex ) {
987         pImpl->exception = SAXParseException(
988                                     ex.Message,
989                                     ex.Context,
990                                     ex.WrappedException,
991                                     pImpl->rDocumentLocator->getPublicId(),
992                                     pImpl->rDocumentLocator->getSystemId(),
993                                     pImpl->rDocumentLocator->getLineNumber(),
994                                     pImpl->rDocumentLocator->getColumnNumber()
995                              );
996         pImpl->bExceptionWasThrown = sal_True;
997     }
998 }
999 
1000 void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
1001 {
1002     SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
1003 
1004     CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
1005 }
1006 
1007 }
1008 using namespace sax_expatwrap;
1009 
1010 
1011 static struct ::cppu::ImplementationEntry g_component_entries[] =
1012 {
1013     {
1014         SaxExpatParser_CreateInstance,
1015         SaxExpatParser::getImplementationName_Static,
1016         SaxExpatParser::getSupportedServiceNames_Static,
1017         ::cppu::createSingleComponentFactory,
1018         0,
1019         0
1020     },
1021     {
1022         SaxWriter_CreateInstance,
1023         SaxWriter_getImplementationName,
1024         SaxWriter_getSupportedServiceNames,
1025         ::cppu::createSingleComponentFactory,
1026         0,
1027         0
1028     },
1029     { 0, 0, 0, 0, 0, 0 }
1030 };
1031 
1032 extern "C"
1033 {
1034 
1035 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
1036     const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
1037 {
1038     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1039 }
1040 
1041 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
1042     const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1043 {
1044     return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, g_component_entries );
1045 }
1046 
1047 
1048 }
1049