office-gobmx/sax/source/expatwrap/sax_expat.cxx
2010-11-22 22:17:17 +01:00

1109 lines
37 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <sal/alloca.h>
#include <vector>
#include <osl/diagnose.h>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/util/XCloneable.hpp>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XParser.hpp>
#include <com/sun/star/xml/sax/SAXParseException.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase2.hxx>
#include <expat.h>
using namespace ::rtl;
using namespace ::std;
using namespace ::osl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::io;
#include "factory.hxx"
#include "attrlistimpl.hxx"
#include "xml2utf.hxx"
namespace sax_expatwrap {
// Useful macros for correct String conversion depending on the choosen expat-mode
#ifdef XML_UNICODE
OUString XmlNChar2OUString( const XML_Char *p , int nLen )
{
if( p ) {
if( sizeof( sal_Unicode ) == sizeof( XML_Char ) )
{
return OUString( (sal_Unicode*)p,nLen);
}
else
{
sal_Unicode *pWchar = (sal_Unicode *)alloca( sizeof( sal_Unicode ) * nLen );
for( int n = 0 ; n < nLen ; n++ ) {
pWchar[n] = (sal_Unicode) p[n];
}
return OUString( pWchar , nLen );
}
}
else {
return OUString();
}
}
OUString XmlChar2OUString( const XML_Char *p )
{
if( p ) {
int nLen;
for( nLen = 0 ; p[nLen] ; nLen ++ )
;
return XmlNChar2OUString( p , nLen );
}
else return OUString();
}
#define XML_CHAR_TO_OUSTRING(x) XmlChar2OUString(x)
#define XML_CHAR_N_TO_USTRING(x,n) XmlNChar2OUString(x,n)
#else
#define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
#define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
#endif
/*
* The following macro encapsulates any call to an event handler.
* It ensures, that exceptions thrown by the event handler are
* treated properly.
*/
#define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
if( ! pThis->bExceptionWasThrown ) { \
try {\
pThis->call;\
}\
catch( SAXParseException &e ) {\
pThis->callErrorHandler( pThis , e );\
}\
catch( SAXException &e ) {\
pThis->callErrorHandler( pThis , SAXParseException(\
e.Message, \
e.Context, \
e.WrappedException,\
pThis->rDocumentLocator->getPublicId(),\
pThis->rDocumentLocator->getSystemId(),\
pThis->rDocumentLocator->getLineNumber(),\
pThis->rDocumentLocator->getColumnNumber()\
) );\
}\
catch( com::sun::star::uno::RuntimeException &e ) {\
pThis->bExceptionWasThrown = sal_True; \
pThis->bRTExceptionWasThrown = sal_True; \
pImpl->rtexception = e; \
}\
}\
((void)0)
#define IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.ParserExpat"
#define SERVICE_NAME "com.sun.star.xml.sax.Parser"
class SaxExpatParser_Impl;
// This class implements the external Parser interface
class SaxExpatParser :
public WeakImplHelper2<
XParser,
XServiceInfo
>
{
public:
SaxExpatParser();
~SaxExpatParser();
public:
// The implementation details
static Sequence< OUString > getSupportedServiceNames_Static(void) throw ();
public:
// The SAX-Parser-Interface
virtual void SAL_CALL parseStream( const InputSource& structSource)
throw ( SAXException,
IOException,
RuntimeException);
virtual void SAL_CALL setDocumentHandler(const Reference< XDocumentHandler > & xHandler)
throw (RuntimeException);
virtual void SAL_CALL setErrorHandler(const Reference< XErrorHandler > & xHandler)
throw (RuntimeException);
virtual void SAL_CALL setDTDHandler(const Reference < XDTDHandler > & xHandler)
throw (RuntimeException);
virtual void SAL_CALL setEntityResolver(const Reference< XEntityResolver >& xResolver)
throw (RuntimeException);
virtual void SAL_CALL setLocale( const Locale &locale ) throw (RuntimeException);
public: // XServiceInfo
OUString SAL_CALL getImplementationName() throw ();
Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw ();
sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw ();
private:
SaxExpatParser_Impl *m_pImpl;
};
//--------------------------------------
// the extern interface
//---------------------------------------
Reference< XInterface > SAL_CALL SaxExpatParser_CreateInstance(
const Reference< XMultiServiceFactory > & ) throw(Exception)
{
SaxExpatParser *p = new SaxExpatParser;
return Reference< XInterface > ( (OWeakObject * ) p );
}
Sequence< OUString > SaxExpatParser::getSupportedServiceNames_Static(void) throw ()
{
Sequence<OUString> aRet(1);
aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICE_NAME) );
return aRet;
}
//---------------------------------------------
// the implementation part
//---------------------------------------------
// Entity binds all information neede for a single file
struct Entity
{
InputSource structSource;
XML_Parser pParser;
XMLFile2UTFConverter converter;
};
class SaxExpatParser_Impl
{
public: // module scope
Mutex aMutex;
Reference< XDocumentHandler > rDocumentHandler;
Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
Reference< XErrorHandler > rErrorHandler;
Reference< XDTDHandler > rDTDHandler;
Reference< XEntityResolver > rEntityResolver;
Reference < XLocator > rDocumentLocator;
Reference < XAttributeList > rAttrList;
AttributeList *pAttrList;
// External entity stack
vector<struct Entity> vecEntity;
void pushEntity( const struct Entity &entity )
{ vecEntity.push_back( entity ); }
void popEntity()
{ vecEntity.pop_back( ); }
struct Entity &getEntity()
{ return vecEntity.back(); }
// Exception cannot be thrown through the C-XmlParser (possible resource leaks),
// therefor the exception must be saved somewhere.
SAXParseException exception;
RuntimeException rtexception;
sal_Bool bExceptionWasThrown;
sal_Bool bRTExceptionWasThrown;
Locale locale;
public:
// the C-Callbacks for the expat parser
void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
void static callbackEndElement(void *userData, const XML_Char *name);
void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
void static callbackProcessingInstruction( void *userData ,
const XML_Char *sTarget ,
const XML_Char *sData );
void static callbackUnparsedEntityDecl( void *userData ,
const XML_Char *entityName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName);
void static callbackNotationDecl( void *userData,
const XML_Char *notationName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
int static callbackExternalEntityRef( XML_Parser parser,
const XML_Char *openEntityNames,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId);
int static callbackUnknownEncoding(void *encodingHandlerData,
const XML_Char *name,
XML_Encoding *info);
void static callbackDefault( void *userData, const XML_Char *s, int len);
void static callbackStartCDATA( void *userData );
void static callbackEndCDATA( void *userData );
void static callbackComment( void *userData , const XML_Char *s );
void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
public:
void parse();
};
extern "C"
{
static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
{
SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
}
static void call_callbackEndElement(void *userData, const XML_Char *name)
{
SaxExpatParser_Impl::callbackEndElement(userData,name);
}
static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
{
SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
}
static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
{
SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
}
static void call_callbackUnparsedEntityDecl(void *userData ,
const XML_Char *entityName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName)
{
SaxExpatParser_Impl::callbackUnparsedEntityDecl(userData,entityName,base,systemId,publicId,notationName);
}
static void call_callbackNotationDecl(void *userData,
const XML_Char *notationName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId)
{
SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
}
static int call_callbackExternalEntityRef(XML_Parser parser,
const XML_Char *openEntityNames,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId)
{
return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
}
static int call_callbackUnknownEncoding(void *encodingHandlerData,
const XML_Char *name,
XML_Encoding *info)
{
return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
}
static void call_callbackDefault( void *userData, const XML_Char *s, int len)
{
SaxExpatParser_Impl::callbackDefault(userData,s,len);
}
static void call_callbackStartCDATA( void *userData )
{
SaxExpatParser_Impl::callbackStartCDATA(userData);
}
static void call_callbackEndCDATA( void *userData )
{
SaxExpatParser_Impl::callbackEndCDATA(userData);
}
static void call_callbackComment( void *userData , const XML_Char *s )
{
SaxExpatParser_Impl::callbackComment(userData,s);
}
}
//---------------------------------------------
// LocatorImpl
//---------------------------------------------
class LocatorImpl :
public WeakImplHelper2< XLocator, com::sun::star::io::XSeekable >
// should use a different interface for stream positions!
{
public:
LocatorImpl( SaxExpatParser_Impl *p )
{
m_pParser = p;
}
public: //XLocator
virtual sal_Int32 SAL_CALL getColumnNumber(void) throw ()
{
return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
}
virtual sal_Int32 SAL_CALL getLineNumber(void) throw ()
{
return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
}
virtual OUString SAL_CALL getPublicId(void) throw ()
{
return m_pParser->getEntity().structSource.sPublicId;
}
virtual OUString SAL_CALL getSystemId(void) throw ()
{
return m_pParser->getEntity().structSource.sSystemId;
}
// XSeekable (only for getPosition)
virtual void SAL_CALL seek( sal_Int64 ) throw()
{
}
virtual sal_Int64 SAL_CALL getPosition() throw()
{
return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
}
virtual ::sal_Int64 SAL_CALL getLength() throw()
{
return 0;
}
private:
SaxExpatParser_Impl *m_pParser;
};
SaxExpatParser::SaxExpatParser( )
{
m_pImpl = new SaxExpatParser_Impl;
LocatorImpl *pLoc = new LocatorImpl( m_pImpl );
m_pImpl->rDocumentLocator = Reference< XLocator > ( pLoc );
// performance-Improvment. Reference is needed when calling the startTag callback.
// Handing out the same object with every call is allowed (see sax-specification)
m_pImpl->pAttrList = new AttributeList;
m_pImpl->rAttrList = Reference< XAttributeList > ( m_pImpl->pAttrList );
m_pImpl->bExceptionWasThrown = sal_False;
m_pImpl->bRTExceptionWasThrown = sal_False;
}
SaxExpatParser::~SaxExpatParser()
{
delete m_pImpl;
}
/***************
*
* parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
* the file-specific initialization work. (During a parser run, external files may be opened)
*
****************/
void SaxExpatParser::parseStream( const InputSource& structSource)
throw (SAXException,
IOException,
RuntimeException)
{
// Only one text at one time
MutexGuard guard( m_pImpl->aMutex );
struct Entity entity;
entity.structSource = structSource;
if( ! entity.structSource.aInputStream.is() )
{
throw SAXException( OUString(RTL_CONSTASCII_USTRINGPARAM("No input source")) ,
Reference< XInterface > () , Any() );
}
entity.converter.setInputStream( entity.structSource.aInputStream );
if( entity.structSource.sEncoding.getLength() )
{
entity.converter.setEncoding(
OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
}
// create parser with proper encoding
entity.pParser = XML_ParserCreate( 0 );
if( ! entity.pParser )
{
throw SAXException( OUString(RTL_CONSTASCII_USTRINGPARAM("Couldn't create parser")) ,
Reference< XInterface > (), Any() );
}
// set all necessary C-Callbacks
XML_SetUserData( entity.pParser , m_pImpl );
XML_SetElementHandler( entity.pParser ,
call_callbackStartElement ,
call_callbackEndElement );
XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
XML_SetProcessingInstructionHandler(entity.pParser ,
call_callbackProcessingInstruction );
XML_SetUnparsedEntityDeclHandler( entity.pParser,
call_callbackUnparsedEntityDecl );
XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
XML_SetExternalEntityRefHandler( entity.pParser,
call_callbackExternalEntityRef);
XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,0);
if( m_pImpl->rExtendedDocumentHandler.is() ) {
// These handlers just delegate calls to the ExtendedHandler. If no extended handler is
// given, these callbacks can be ignored
XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
XML_SetCommentHandler( entity.pParser, call_callbackComment );
XML_SetCdataSectionHandler( entity.pParser ,
call_callbackStartCDATA ,
call_callbackEndCDATA );
}
m_pImpl->exception = SAXParseException();
m_pImpl->pushEntity( entity );
try
{
// start the document
if( m_pImpl->rDocumentHandler.is() ) {
m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
m_pImpl->rDocumentHandler->startDocument();
}
m_pImpl->parse();
// finish document
if( m_pImpl->rDocumentHandler.is() ) {
m_pImpl->rDocumentHandler->endDocument();
}
}
// catch( SAXParseException &e )
// {
// m_pImpl->popEntity();
// XML_ParserFree( entity.pParser );
// Any aAny;
// aAny <<= e;
// throw SAXException( e.Message, e.Context, aAny );
// }
catch( SAXException & )
{
m_pImpl->popEntity();
XML_ParserFree( entity.pParser );
throw;
}
catch( IOException & )
{
m_pImpl->popEntity();
XML_ParserFree( entity.pParser );
throw;
}
catch( RuntimeException & )
{
m_pImpl->popEntity();
XML_ParserFree( entity.pParser );
throw;
}
m_pImpl->popEntity();
XML_ParserFree( entity.pParser );
}
void SaxExpatParser::setDocumentHandler(const Reference< XDocumentHandler > & xHandler)
throw (RuntimeException)
{
m_pImpl->rDocumentHandler = xHandler;
m_pImpl->rExtendedDocumentHandler =
Reference< XExtendedDocumentHandler >( xHandler , UNO_QUERY );
}
void SaxExpatParser::setErrorHandler(const Reference< XErrorHandler > & xHandler)
throw (RuntimeException)
{
m_pImpl->rErrorHandler = xHandler;
}
void SaxExpatParser::setDTDHandler(const Reference< XDTDHandler > & xHandler)
throw (RuntimeException)
{
m_pImpl->rDTDHandler = xHandler;
}
void SaxExpatParser::setEntityResolver(const Reference < XEntityResolver > & xResolver)
throw (RuntimeException)
{
m_pImpl->rEntityResolver = xResolver;
}
void SaxExpatParser::setLocale( const Locale & locale ) throw (RuntimeException)
{
m_pImpl->locale = locale;
}
// XServiceInfo
OUString SaxExpatParser::getImplementationName() throw ()
{
return OUString::createFromAscii( IMPLEMENTATION_NAME );
}
// XServiceInfo
sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw ()
{
Sequence< OUString > aSNL = getSupportedServiceNames();
const OUString * pArray = aSNL.getConstArray();
for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
if( pArray[i] == ServiceName )
return sal_True;
return sal_False;
}
// XServiceInfo
Sequence< OUString > SaxExpatParser::getSupportedServiceNames(void) throw ()
{
Sequence<OUString> seq(1);
seq.getArray()[0] = OUString::createFromAscii( SERVICE_NAME );
return seq;
}
/*---------------------------------------
*
* Helper functions and classes
*
*
*-------------------------------------------*/
OUString getErrorMessage( XML_Error xmlE, OUString sSystemId , sal_Int32 nLine )
{
OUString Message;
if( XML_ERROR_NONE == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("No"));
}
else if( XML_ERROR_NO_MEMORY == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("no memory"));
}
else if( XML_ERROR_SYNTAX == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("syntax"));
}
else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("no elements"));
}
else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("invalid token"));
}
else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("unclosed token"));
}
else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("partial char"));
}
else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("tag mismatch"));
}
else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("duplicate attribute"));
}
else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("junk after doc element"));
}
else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("parameter entity reference"));
}
else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("undefined entity"));
}
else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("recursive entity reference"));
}
else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("async entity"));
}
else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("bad char reference"));
}
else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("binary entity reference"));
}
else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("attribute external entity reference"));
}
else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("misplaced xml processing instruction"));
}
else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("unknown encoding"));
}
else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("incorrect encoding"));
}
else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("unclosed cdata section"));
}
else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("external entity reference"));
}
else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
Message = OUString(RTL_CONSTASCII_USTRINGPARAM("not standalone"));
}
OUString str(RTL_CONSTASCII_USTRINGPARAM("["));
str += sSystemId;
str += OUString(RTL_CONSTASCII_USTRINGPARAM(" line "));
str += OUString::valueOf( nLine );
str += OUString(RTL_CONSTASCII_USTRINGPARAM("]: "));
str += Message;
str += OUString(RTL_CONSTASCII_USTRINGPARAM("error"));
return str;
}
// starts parsing with actual parser !
void SaxExpatParser_Impl::parse( )
{
const int nBufSize = 16*1024;
int nRead = nBufSize;
Sequence< sal_Int8 > seqOut(nBufSize);
while( nRead ) {
nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
if( ! nRead ) {
XML_Parse( getEntity().pParser ,
( const char * ) seqOut.getArray() ,
0 ,
1 );
break;
}
sal_Bool bContinue = ( XML_Parse( getEntity().pParser ,
(const char *) seqOut.getArray(),
nRead,
0 ) != 0 );
if( ! bContinue || this->bExceptionWasThrown ) {
if ( this->bRTExceptionWasThrown )
throw rtexception;
// Error during parsing !
XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
OUString sSystemId = rDocumentLocator->getSystemId();
sal_Int32 nLine = rDocumentLocator->getLineNumber();
SAXParseException aExcept(
getErrorMessage(xmlE , sSystemId, nLine) ,
Reference< XInterface >(),
Any( &exception , getCppuType( &exception) ),
rDocumentLocator->getPublicId(),
rDocumentLocator->getSystemId(),
rDocumentLocator->getLineNumber(),
rDocumentLocator->getColumnNumber()
);
if( rErrorHandler.is() ) {
// error handler is set, so the handler may throw the exception
Any a;
a <<= aExcept;
rErrorHandler->fatalError( a );
}
// Error handler has not thrown an exception, but parsing cannot go on,
// so an exception MUST be thrown.
throw aExcept;
} // if( ! bContinue )
} // while
}
//------------------------------------------
//
// The C-Callbacks
//
//-----------------------------------------
void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
const XML_Char *pwName ,
const XML_Char **awAttributes )
{
// in case of two concurrent threads, there is only the danger of an leak,
// which is neglectable for one string
static OUString g_CDATA( RTL_CONSTASCII_USTRINGPARAM( "CDATA" ) );
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDocumentHandler.is() ) {
int i = 0;
pImpl->pAttrList->clear();
while( awAttributes[i] ) {
OSL_ASSERT( awAttributes[i+1] );
pImpl->pAttrList->addAttribute(
XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
g_CDATA , // expat doesn't know types
XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
i +=2;
}
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
pImpl ,
rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
pImpl->rAttrList ) );
}
}
void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDocumentHandler.is() ) {
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
}
}
void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDocumentHandler.is() ) {
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
}
}
void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
const XML_Char *sTarget ,
const XML_Char *sData )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDocumentHandler.is() ) {
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
pImpl ,
rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
XML_CHAR_TO_OUSTRING( sData ) ) );
}
}
void SaxExpatParser_Impl::callbackUnparsedEntityDecl(void *pvThis ,
const XML_Char *entityName,
const XML_Char * /*base*/,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName)
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDTDHandler.is() ) {
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
pImpl ,
rDTDHandler->unparsedEntityDecl(
XML_CHAR_TO_OUSTRING( entityName ),
XML_CHAR_TO_OUSTRING( publicId ) ,
XML_CHAR_TO_OUSTRING( systemId ) ,
XML_CHAR_TO_OUSTRING( notationName ) ) );
}
}
void SaxExpatParser_Impl::callbackNotationDecl( void *pvThis,
const XML_Char *notationName,
const XML_Char * /*base*/,
const XML_Char *systemId,
const XML_Char *publicId)
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
if( pImpl->rDTDHandler.is() ) {
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) ,
XML_CHAR_TO_OUSTRING( publicId ) ,
XML_CHAR_TO_OUSTRING( systemId ) ) );
}
}
int SaxExpatParser_Impl::callbackExternalEntityRef( XML_Parser parser,
const XML_Char *context,
const XML_Char * /*base*/,
const XML_Char *systemId,
const XML_Char *publicId)
{
sal_Bool bOK = sal_True;
InputSource source;
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)XML_GetUserData( parser ));
struct Entity entity;
if( pImpl->rEntityResolver.is() ) {
try
{
entity.structSource = pImpl->rEntityResolver->resolveEntity(
XML_CHAR_TO_OUSTRING( publicId ) ,
XML_CHAR_TO_OUSTRING( systemId ) );
}
catch( SAXParseException & e )
{
pImpl->exception = e;
bOK = sal_False;
}
catch( SAXException & e )
{
pImpl->exception = SAXParseException(
e.Message , e.Context , e.WrappedException ,
pImpl->rDocumentLocator->getPublicId(),
pImpl->rDocumentLocator->getSystemId(),
pImpl->rDocumentLocator->getLineNumber(),
pImpl->rDocumentLocator->getColumnNumber() );
bOK = sal_False;
}
}
if( entity.structSource.aInputStream.is() ) {
entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 );
if( ! entity.pParser )
{
return sal_False;
}
entity.converter.setInputStream( entity.structSource.aInputStream );
pImpl->pushEntity( entity );
try
{
pImpl->parse();
}
catch( SAXParseException & e )
{
pImpl->exception = e;
bOK = sal_False;
}
catch( IOException &e )
{
pImpl->exception.WrappedException <<= e;
bOK = sal_False;
}
catch( RuntimeException &e )
{
pImpl->exception.WrappedException <<=e;
bOK = sal_False;
}
pImpl->popEntity();
XML_ParserFree( entity.pParser );
}
return bOK;
}
int SaxExpatParser_Impl::callbackUnknownEncoding(void * /*encodingHandlerData*/,
const XML_Char * /*name*/,
XML_Encoding * /*info*/)
{
return 0;
}
void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
}
void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
}
void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
}
void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
const SAXParseException & e )
{
try
{
if( pImpl->rErrorHandler.is() ) {
Any a;
a <<= e;
pImpl->rErrorHandler->error( a );
}
else {
pImpl->exception = e;
pImpl->bExceptionWasThrown = sal_True;
}
}
catch( SAXParseException & ex ) {
pImpl->exception = ex;
pImpl->bExceptionWasThrown = sal_True;
}
catch( SAXException & ex ) {
pImpl->exception = SAXParseException(
ex.Message,
ex.Context,
ex.WrappedException,
pImpl->rDocumentLocator->getPublicId(),
pImpl->rDocumentLocator->getSystemId(),
pImpl->rDocumentLocator->getLineNumber(),
pImpl->rDocumentLocator->getColumnNumber()
);
pImpl->bExceptionWasThrown = sal_True;
}
}
void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
{
SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
}
}
using namespace sax_expatwrap;
extern "C"
{
void SAL_CALL component_getImplementationEnvironment(
const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
{
*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
sal_Bool SAL_CALL component_writeInfo(
void * /*pServiceManager*/, void * pRegistryKey )
{
if (pRegistryKey)
{
try
{
Reference< XRegistryKey > xKey(
reinterpret_cast< XRegistryKey * >( pRegistryKey ) );
Reference< XRegistryKey > xNewKey = xKey->createKey(
OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) );
xNewKey->createKey( OUString::createFromAscii( SERVICE_NAME ) );
xNewKey = xKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM("/")) +
SaxWriter_getImplementationName()+
OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) );
xNewKey->createKey( SaxWriter_getServiceName() );
return sal_True;
}
catch (InvalidRegistryException &)
{
OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
}
}
return sal_False;
}
void * SAL_CALL component_getFactory(
const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
{
void * pRet = 0;
if (pServiceManager )
{
Reference< XSingleServiceFactory > xRet;
Reference< XMultiServiceFactory > xSMgr =
reinterpret_cast< XMultiServiceFactory * > ( pServiceManager );
OUString aImplementationName = OUString::createFromAscii( pImplName );
if (aImplementationName ==
OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ) )
{
xRet = createSingleFactory( xSMgr, aImplementationName,
SaxExpatParser_CreateInstance,
SaxExpatParser::getSupportedServiceNames_Static() );
}
else if ( aImplementationName == SaxWriter_getImplementationName() )
{
xRet = createSingleFactory( xSMgr, aImplementationName,
SaxWriter_CreateInstance,
SaxWriter_getSupportedServiceNames() );
}
if (xRet.is())
{
xRet->acquire();
pRet = xRet.get();
}
}
return pRet;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */