1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlconfig.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_svx.hxx"
34 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
35 #include <com/sun/star/xml/sax/InputSource.hpp>
36 #include <com/sun/star/xml/sax/XParser.hpp>
37 #include <com/sun/star/xml/sax/SAXParseException.hpp>
38 #include <com/sun/star/io/IOException.hpp>
39 #include <cppuhelper/implbase1.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <unotools/ucbstreamhelper.hxx>
42 #include <unotools/streamwrap.hxx>
43 #include <tools/debug.hxx>
44 #include "comphelper/anytostring.hxx"
45 #include "cppuhelper/exc_hlp.hxx"
46 #include "rtl/ref.hxx"
48 #include <svx/msdffimp.hxx>
50 #include "xmlconfig.hxx"
56 using ::rtl::OUString
;
57 using ::com::sun::star::io::XInputStream
;
58 using ::com::sun::star::io::IOException
;
60 using namespace ::com::sun::star::uno
;
61 using namespace ::com::sun::star::xml::sax
;
63 ///////////////////////////////////////////////////////////////////////
65 AtomConfigMap gAtomConfigMap
;
67 ///////////////////////////////////////////////////////////////////////
69 class ConfigHandler
: public ::cppu::WeakAggImplHelper1
<XDocumentHandler
>
73 virtual void SAL_CALL
startDocument(void) throw( SAXException
, RuntimeException
);
74 virtual void SAL_CALL
endDocument(void) throw( SAXException
, RuntimeException
);
75 virtual void SAL_CALL
startElement(const OUString
& aName
, const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
, RuntimeException
);
76 virtual void SAL_CALL
endElement(const OUString
& aName
) throw( SAXException
, RuntimeException
);
77 virtual void SAL_CALL
characters(const OUString
& aChars
) throw( SAXException
, RuntimeException
);
78 virtual void SAL_CALL
ignorableWhitespace(const OUString
& aWhitespaces
) throw( SAXException
, RuntimeException
);
79 virtual void SAL_CALL
processingInstruction(const OUString
& aTarget
, const OUString
& aData
) throw( SAXException
, RuntimeException
);
80 virtual void SAL_CALL
setDocumentLocator(const Reference
< XLocator
> & xLocator
) throw( SAXException
, RuntimeException
);
83 void errorThrow( const OUString
& rErrorMessage
) throw (SAXException
);
84 ElementConfigType
parseType( const OUString
& rErrorMessage
) throw ( SAXException
);
85 void addElement( ElementConfigPtr
& rElementConfig
) throw ( SAXException
);
86 OUString
getAttribute( const Reference
< XAttributeList
> & xAttribs
, const sal_Char
* pName
) throw( SAXException
);
88 ElementConfigPtr
importAtomConfig( const Reference
< XAttributeList
> & xAttribs
, bool bIsContainer
) throw( SAXException
);
89 ElementConfigPtr
importElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
90 ElementConfigPtr
importSwitchConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
91 ElementConfigPtr
importCaseConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
92 ElementConfigPtr
importValueElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
94 std::stack
< ElementConfigPtr
> maElementStack
;
97 void ConfigHandler::errorThrow( const OUString
& rErrorMessage
) throw (SAXException
)
99 Reference
< XInterface
> aContext
;
100 Any aWrappedException
;
101 throw SAXException(rErrorMessage
, aContext
, aWrappedException
);
104 ElementConfigType
ConfigHandler::parseType( const OUString
& sType
) throw (SAXException
)
106 if( sType
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("uint") ) )
110 else if( sType
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") ) )
114 else if( sType
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unistring") ) )
116 return ECT_UNISTRING
;
118 else if( sType
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") ) )
122 else if( sType
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hexdump") ) )
127 OUString
aMessage( RTL_CONSTASCII_USTRINGPARAM( "unknown type: " ) );
129 errorThrow( aMessage
);
135 void ConfigHandler::addElement( ElementConfigPtr
& rElementConfig
) throw ( SAXException
)
137 ElementConfigContainer
* pParent
= dynamic_cast< ElementConfigContainer
* >( maElementStack
.top().get() );
140 errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal parent for element" ) ) );
143 pParent
->addElementConfig( rElementConfig
);
146 OUString
ConfigHandler::getAttribute( const Reference
< XAttributeList
> & xAttribs
, const sal_Char
* pName
) throw( SAXException
)
148 OUString
aName( OUString::createFromAscii( pName
) );
150 const sal_Int16 nAttrCount
= xAttribs
.is() ? xAttribs
->getLength() : 0;
152 for(i
=0; i
< nAttrCount
; i
++)
154 if( xAttribs
->getNameByIndex( i
) == aName
)
155 return xAttribs
->getValueByIndex( i
);
158 OUString
aMessage( RTL_CONSTASCII_USTRINGPARAM( "missing required attribute: ") );
160 errorThrow( aMessage
);
165 void SAL_CALL
ConfigHandler::startDocument(void) throw( SAXException
, RuntimeException
)
169 void SAL_CALL
ConfigHandler::endDocument(void) throw( SAXException
, RuntimeException
)
173 void SAL_CALL
ConfigHandler::startElement(const OUString
& aName
, const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
, RuntimeException
)
175 ElementConfigPtr pElement
;
177 if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) )
182 if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "container" ) ) )
184 pElement
= importAtomConfig( xAttribs
, true );
186 else if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "atom" ) ) )
188 pElement
= importAtomConfig( xAttribs
, false );
190 else if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "element" ) ) )
192 pElement
= importElementConfig( xAttribs
);
194 else if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "value" ) ) )
196 pElement
= importValueElementConfig( xAttribs
);
198 else if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "switch" ) ) )
200 pElement
= importSwitchConfig( xAttribs
);
202 else if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "case" ) ) )
204 pElement
= importCaseConfig( xAttribs
);
207 if( !pElement
.get() )
209 OUString
aMessage( OUString( RTL_CONSTASCII_USTRINGPARAM("unknown config element: ")) );
211 errorThrow( aMessage
);
214 maElementStack
.push( pElement
);
217 sal_Int32
toInt( const OUString
& rText
)
219 if( rText
.compareToAscii("0x",2) == 0)
221 sal_Int32 nValue
= 0;
222 const sal_Unicode
*p
= rText
;
224 sal_Int32 nLength
= rText
.getLength() - 2;
225 while( (nLength
--) > 0 )
228 if( *p
>= '0' && *p
<= '9' )
232 else if( *p
>= 'a' && *p
<= 'f' )
234 nValue
+= *p
- ('a' - 10);
236 else if( *p
>= 'A' && *p
<= 'F' )
238 nValue
+= *p
- ('A' - 10 );
247 return rText
.toInt32();
251 ElementConfigPtr
ConfigHandler::importAtomConfig( const Reference
< XAttributeList
> & xAttribs
, bool bIsContainer
) throw (SAXException
)
253 if( !maElementStack
.empty() )
254 errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM("atom elements must be root" ) ) );
256 ElementConfigPtr
aPtr( new AtomConfig( getAttribute(xAttribs
,"name"), bIsContainer
) );
257 gAtomConfigMap
[ (UINT16
)toInt(getAttribute(xAttribs
,"id"))] = aPtr
;
261 ElementConfigPtr
ConfigHandler::importElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
263 ElementConfigType nType
= parseType( getAttribute( xAttribs
, "type" ) );
264 ElementConfigPtr
pElementConfig( new ElementConfigContainer( getAttribute( xAttribs
, "name" ), nType
) );
265 addElement( pElementConfig
);
266 return pElementConfig
;
269 ElementConfigPtr
ConfigHandler::importValueElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
271 ElementConfigPtr
pElementConfig( new ElementValueConfig( getAttribute( xAttribs
, "name" ), getAttribute( xAttribs
, "value" ) ) );
272 addElement( pElementConfig
);
273 return pElementConfig
;
276 ElementConfigPtr
ConfigHandler::importSwitchConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
278 ElementConfigType nType
= parseType( getAttribute( xAttribs
, "type" ) );
279 ElementConfigPtr
pElementConfig( new SwitchElementConfig( nType
) );
280 addElement( pElementConfig
);
281 return pElementConfig
;
284 ElementConfigPtr
ConfigHandler::importCaseConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
286 ElementConfigPtr
pElementConfig( new CaseElementConfig( getAttribute( xAttribs
, "value" ) ) );
287 addElement( pElementConfig
);
288 return pElementConfig
;
291 void SAL_CALL
ConfigHandler::endElement(const OUString
& aName
) throw( SAXException
, RuntimeException
)
293 if( aName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) )
298 maElementStack
.pop();
301 void SAL_CALL
ConfigHandler::characters(const OUString
& aChars
) throw( SAXException
, RuntimeException
)
305 void SAL_CALL
ConfigHandler::ignorableWhitespace(const OUString
& aWhitespaces
) throw( SAXException
, RuntimeException
)
309 void SAL_CALL
ConfigHandler::processingInstruction(const OUString
& aTarget
, const OUString
& aData
) throw( SAXException
, RuntimeException
)
313 void SAL_CALL
ConfigHandler::setDocumentLocator(const Reference
< XLocator
> & xLocator
) throw( SAXException
, RuntimeException
)
317 void load_config( const OUString
& rPath
)
322 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( rPath
, STREAM_READ
);
323 Reference
<XInputStream
> xInputStream( new utl::OInputStreamWrapper( pIStm
, sal_True
) );
325 // prepare ParserInputSrouce
326 InputSource aParserInput
;
327 aParserInput
.sSystemId
= rPath
;
328 aParserInput
.aInputStream
= xInputStream
;
331 Reference
< XParser
> xParser(
332 comphelper::getProcessServiceFactory()->createInstance(
333 OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
337 ConfigHandler
* pConfigHandler
= new ConfigHandler();
338 Reference
< XDocumentHandler
> xFilter( pConfigHandler
);
340 // connect parser and filter
341 xParser
->setDocumentHandler( xFilter
);
343 // finally, parser the stream
344 xParser
->parseStream( aParserInput
);
346 catch( Exception
& r
)
349 (rtl::OString("load_config(), "
350 "exception caught: ") +
351 rtl::OUStringToOString(
352 comphelper::anyToString( cppu::getCaughtException() ),
353 RTL_TEXTENCODING_UTF8
)).getStr() );
359 ///////////////////////////////////////////////////////////////////////
361 rtl::OUString
ElementConfig::format( SvStream
& rStream
, sal_Size
& nLength
) const
364 if( maName
.getLength() )
367 aRet
+= OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) );
372 case ECT_BYTE
: aRet
+= dump_byte( rStream
, nLength
); break;
373 case ECT_UINT
: aRet
+= dump_uint( rStream
, nLength
); break;
374 case ECT_UNISTRING
: aRet
+= dump_unistring( rStream
, nLength
); break;
375 case ETC_FLOAT
: aRet
+= dump_float( rStream
, nLength
); break;
377 default: aRet
+= dump_hex( rStream
, nLength
); break;
383 rtl::OUString
ElementConfig::dump_hex( SvStream
& rStream
, sal_Size
& nLength
)
386 OUString aOut
, aEmpty
;
387 OUString aHex
, aAscii
;
390 while( nLength
&& (rStream
.GetError() == 0) )
397 sprintf( buffer
, "%02x ", i
);
398 aHex
+= OUString::createFromAscii( buffer
);
403 aAscii
+= OUString( (sal_Unicode
) c
);
406 if( (nRow
== 16) || (nLength
==0) )
408 while( aHex
.getLength() < (16*3) )
409 aHex
+= OUString( RTL_CONSTASCII_USTRINGPARAM(" ") );
412 aOut
+= OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) );
425 rtl::OUString
ElementConfig::dump_byte( SvStream
& rStream
, sal_Size
& nLength
)
428 if( nLength
>= sizeof(sal_Char
) )
434 sprintf( buffer
, "%u", (int)c
);
435 aRet
+= OUString::createFromAscii( buffer
);
436 nLength
-= sizeof(sal_Char
);
442 rtl::OUString
ElementConfig::dump_uint( SvStream
& rStream
, sal_Size
& nLength
)
445 if( nLength
>= sizeof( sal_uInt32
) )
451 sprintf( buffer
, "%u", c
);
452 aRet
+= OUString::createFromAscii( buffer
);
453 nLength
-= sizeof( sal_uInt32
);
459 rtl::OUString
ElementConfig::dump_unistring( SvStream
& rStream
, sal_Size
& nLength
)
462 SvxMSDffManager::MSDFFReadZString( rStream
, aString
, nLength
, sal_True
);
467 rtl::OUString
ElementConfig::dump_float( SvStream
& rStream
, sal_Size
& nLength
)
470 if( nLength
>= sizeof( float ) )
476 sprintf( buffer
, "%g", (double)c
);
477 aRet
+= OUString::createFromAscii( buffer
);
478 nLength
-= sizeof( float );
484 ///////////////////////////////////////////////////////////////////////
486 rtl::OUString
ElementConfigContainer::format( SvStream
& rStream
, sal_Size
& nLength
) const
490 if( getType() == ETC_CONTAINER
)
493 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
494 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
495 while( (aIter
!= aEnd
) && (nLength
> 0) )
497 aRet
+= (*aIter
++)->format( rStream
, nLength
);
498 if( (aIter
!= aEnd
) || (nLength
!= 0) )
499 aRet
+= OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) );
503 aRet
+= ElementConfig::dump_hex( rStream
, nLength
);
508 if( aRet
.getLength() )
509 aRet
+= OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) );
514 case ECT_BYTE
: aValue
= dump_byte( rStream
, nLength
); break;
515 case ECT_UINT
: aValue
= dump_uint( rStream
, nLength
); break;
516 case ECT_UNISTRING
: aValue
= dump_unistring( rStream
, nLength
); break;
517 case ETC_FLOAT
: aValue
= dump_float( rStream
, nLength
); break;
519 default: aValue
= dump_hex( rStream
, nLength
); break;
522 if( aValue
.getLength() )
524 if( !maElementConfigList
.empty() )
526 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
527 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
528 while( (aIter
!= aEnd
) && (nLength
> 0) )
530 ElementValueConfig
* pValue
= dynamic_cast< ElementValueConfig
* >( (*aIter
++).get() );
531 if( pValue
&& pValue
->getValue() == aValue
)
533 aValue
= pValue
->getName();
541 aValue
= OUString( RTL_CONSTASCII_USTRINGPARAM("<empty!?>") );
550 ///////////////////////////////////////////////////////////////////////
552 rtl::OUString
SwitchElementConfig::format( SvStream
& rStream
, sal_Size
& nLength
) const
558 case ECT_BYTE
: aValue
= dump_byte( rStream
, nLength
); break;
559 case ECT_UINT
: aValue
= dump_uint( rStream
, nLength
); break;
560 case ETC_FLOAT
: aValue
= dump_float( rStream
, nLength
); break;
561 case ECT_UNISTRING
: aValue
= dump_unistring( rStream
, nLength
); break;
564 if( aValue
.getLength() )
566 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
567 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
568 while( (aIter
!= aEnd
) && (nLength
> 0) )
570 CaseElementConfig
* pCase
= dynamic_cast< CaseElementConfig
* >( (*aIter
++).get() );
571 if( pCase
&& pCase
->getValue() == aValue
)
572 return pCase
->format( rStream
, nLength
);
576 return ElementConfig::dump_hex( rStream
, nLength
);