1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
31 #include <com/sun/star/xml/sax/InputSource.hpp>
32 #include <com/sun/star/xml/sax/XParser.hpp>
33 #include <com/sun/star/xml/sax/SAXParseException.hpp>
34 #include <com/sun/star/io/IOException.hpp>
35 #include <cppuhelper/implbase1.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #include <unotools/streamwrap.hxx>
39 #include "comphelper/anytostring.hxx"
40 #include "cppuhelper/exc_hlp.hxx"
41 #include "rtl/ref.hxx"
43 #include <svx/msdffimp.hxx>
45 #include "xmlconfig.hxx"
51 using ::rtl::OUString
;
52 using ::com::sun::star::io::XInputStream
;
53 using ::com::sun::star::io::IOException
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::xml::sax
;
58 ///////////////////////////////////////////////////////////////////////
60 AtomConfigMap gAtomConfigMap
;
62 ///////////////////////////////////////////////////////////////////////
64 class ConfigHandler
: public ::cppu::WeakAggImplHelper1
<XDocumentHandler
>
68 virtual void SAL_CALL
startDocument(void) throw( SAXException
, RuntimeException
);
69 virtual void SAL_CALL
endDocument(void) throw( SAXException
, RuntimeException
);
70 virtual void SAL_CALL
startElement(const OUString
& aName
, const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
, RuntimeException
);
71 virtual void SAL_CALL
endElement(const OUString
& aName
) throw( SAXException
, RuntimeException
);
72 virtual void SAL_CALL
characters(const OUString
& aChars
) throw( SAXException
, RuntimeException
);
73 virtual void SAL_CALL
ignorableWhitespace(const OUString
& aWhitespaces
) throw( SAXException
, RuntimeException
);
74 virtual void SAL_CALL
processingInstruction(const OUString
& aTarget
, const OUString
& aData
) throw( SAXException
, RuntimeException
);
75 virtual void SAL_CALL
setDocumentLocator(const Reference
< XLocator
> & xLocator
) throw( SAXException
, RuntimeException
);
78 void errorThrow( const OUString
& rErrorMessage
) throw (SAXException
);
79 ElementConfigType
parseType( const OUString
& rErrorMessage
) throw ( SAXException
);
80 void addElement( ElementConfigPtr
& rElementConfig
) throw ( SAXException
);
81 OUString
getAttribute( const Reference
< XAttributeList
> & xAttribs
, const sal_Char
* pName
) throw( SAXException
);
83 ElementConfigPtr
importAtomConfig( const Reference
< XAttributeList
> & xAttribs
, bool bIsContainer
) throw( SAXException
);
84 ElementConfigPtr
importElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
85 ElementConfigPtr
importSwitchConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
86 ElementConfigPtr
importCaseConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
87 ElementConfigPtr
importValueElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
);
89 std::stack
< ElementConfigPtr
> maElementStack
;
92 void ConfigHandler::errorThrow( const OUString
& rErrorMessage
) throw (SAXException
)
94 Reference
< XInterface
> aContext
;
95 Any aWrappedException
;
96 throw SAXException(rErrorMessage
, aContext
, aWrappedException
);
99 ElementConfigType
ConfigHandler::parseType( const OUString
& sType
) throw (SAXException
)
101 if ( sType
== "uint" )
105 else if ( sType
== "byte" )
109 else if ( sType
== "unistring" )
111 return ECT_UNISTRING
;
113 else if ( sType
== "float" )
117 else if ( sType
== "hexdump" )
122 OUString
aMessage( "unknown type: " );
124 errorThrow( aMessage
);
130 void ConfigHandler::addElement( ElementConfigPtr
& rElementConfig
) throw ( SAXException
)
132 ElementConfigContainer
* pParent
= dynamic_cast< ElementConfigContainer
* >( maElementStack
.top().get() );
135 errorThrow( OUString( "illegal parent for element" ) );
138 pParent
->addElementConfig( rElementConfig
);
141 OUString
ConfigHandler::getAttribute( const Reference
< XAttributeList
> & xAttribs
, const sal_Char
* pName
) throw( SAXException
)
143 OUString
aName( OUString::createFromAscii( pName
) );
145 const sal_Int16 nAttrCount
= xAttribs
.is() ? xAttribs
->getLength() : 0;
147 for(i
=0; i
< nAttrCount
; i
++)
149 if( xAttribs
->getNameByIndex( i
) == aName
)
150 return xAttribs
->getValueByIndex( i
);
153 OUString
aMessage( "missing required attribute: " );
155 errorThrow( aMessage
);
160 void SAL_CALL
ConfigHandler::startDocument(void) throw( SAXException
, RuntimeException
)
164 void SAL_CALL
ConfigHandler::endDocument(void) throw( SAXException
, RuntimeException
)
168 void SAL_CALL
ConfigHandler::startElement(const OUString
& aName
, const Reference
< XAttributeList
> & xAttribs
) throw( SAXException
, RuntimeException
)
170 ElementConfigPtr pElement
;
172 if ( aName
== "config" )
177 if ( aName
== "container" )
179 pElement
= importAtomConfig( xAttribs
, true );
181 else if ( aName
== "atom" )
183 pElement
= importAtomConfig( xAttribs
, false );
185 else if ( aName
== "element" )
187 pElement
= importElementConfig( xAttribs
);
189 else if ( aName
== "value" )
191 pElement
= importValueElementConfig( xAttribs
);
193 else if ( aName
== "switch" )
195 pElement
= importSwitchConfig( xAttribs
);
197 else if ( aName
== "case" )
199 pElement
= importCaseConfig( xAttribs
);
202 if( !pElement
.get() )
204 OUString
aMessage( OUString( "unknown config element: ") );
206 errorThrow( aMessage
);
209 maElementStack
.push( pElement
);
212 sal_Int32
toInt( const OUString
& rText
)
214 if( rText
.compareToAscii("0x",2) == 0)
216 sal_Int32 nValue
= 0;
217 const sal_Unicode
*p
= rText
;
219 sal_Int32 nLength
= rText
.getLength() - 2;
220 while( (nLength
--) > 0 )
223 if( *p
>= '0' && *p
<= '9' )
227 else if( *p
>= 'a' && *p
<= 'f' )
229 nValue
+= *p
- ('a' - 10);
231 else if( *p
>= 'A' && *p
<= 'F' )
233 nValue
+= *p
- ('A' - 10 );
242 return rText
.toInt32();
246 ElementConfigPtr
ConfigHandler::importAtomConfig( const Reference
< XAttributeList
> & xAttribs
, bool bIsContainer
) throw (SAXException
)
248 if( !maElementStack
.empty() )
249 errorThrow( OUString( "atom elements must be root" ) );
251 ElementConfigPtr
aPtr( new AtomConfig( getAttribute(xAttribs
,"name"), bIsContainer
) );
252 gAtomConfigMap
[ (UINT16
)toInt(getAttribute(xAttribs
,"id"))] = aPtr
;
256 ElementConfigPtr
ConfigHandler::importElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
258 ElementConfigType nType
= parseType( getAttribute( xAttribs
, "type" ) );
259 ElementConfigPtr
pElementConfig( new ElementConfigContainer( getAttribute( xAttribs
, "name" ), nType
) );
260 addElement( pElementConfig
);
261 return pElementConfig
;
264 ElementConfigPtr
ConfigHandler::importValueElementConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
266 ElementConfigPtr
pElementConfig( new ElementValueConfig( getAttribute( xAttribs
, "name" ), getAttribute( xAttribs
, "value" ) ) );
267 addElement( pElementConfig
);
268 return pElementConfig
;
271 ElementConfigPtr
ConfigHandler::importSwitchConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
273 ElementConfigType nType
= parseType( getAttribute( xAttribs
, "type" ) );
274 ElementConfigPtr
pElementConfig( new SwitchElementConfig( nType
) );
275 addElement( pElementConfig
);
276 return pElementConfig
;
279 ElementConfigPtr
ConfigHandler::importCaseConfig( const Reference
< XAttributeList
> & xAttribs
) throw (SAXException
)
281 ElementConfigPtr
pElementConfig( new CaseElementConfig( getAttribute( xAttribs
, "value" ) ) );
282 addElement( pElementConfig
);
283 return pElementConfig
;
286 void SAL_CALL
ConfigHandler::endElement(const OUString
& aName
) throw( SAXException
, RuntimeException
)
288 if ( aName
== "config" )
293 maElementStack
.pop();
296 void SAL_CALL
ConfigHandler::characters(const OUString
& aChars
) throw( SAXException
, RuntimeException
)
300 void SAL_CALL
ConfigHandler::ignorableWhitespace(const OUString
& aWhitespaces
) throw( SAXException
, RuntimeException
)
304 void SAL_CALL
ConfigHandler::processingInstruction(const OUString
& aTarget
, const OUString
& aData
) throw( SAXException
, RuntimeException
)
308 void SAL_CALL
ConfigHandler::setDocumentLocator(const Reference
< XLocator
> & xLocator
) throw( SAXException
, RuntimeException
)
312 void load_config( const OUString
& rPath
)
317 SvStream
* pIStm
= ::utl::UcbStreamHelper::CreateStream( rPath
, STREAM_READ
);
318 Reference
<XInputStream
> xInputStream( new utl::OInputStreamWrapper( pIStm
, sal_True
) );
320 // prepare ParserInputSrouce
321 InputSource aParserInput
;
322 aParserInput
.sSystemId
= rPath
;
323 aParserInput
.aInputStream
= xInputStream
;
326 Reference
< XParser
> xParser(
327 comphelper::getProcessServiceFactory()->createInstance(
328 OUString("com.sun.star.xml.sax.Parser") ),
332 ConfigHandler
* pConfigHandler
= new ConfigHandler();
333 Reference
< XDocumentHandler
> xFilter( pConfigHandler
);
335 // connect parser and filter
336 xParser
->setDocumentHandler( xFilter
);
338 // finally, parser the stream
339 xParser
->parseStream( aParserInput
);
344 (rtl::OString("load_config(), "
345 "exception caught: ") +
346 rtl::OUStringToOString(
347 comphelper::anyToString( cppu::getCaughtException() ),
348 RTL_TEXTENCODING_UTF8
)).getStr() );
352 ///////////////////////////////////////////////////////////////////////
354 rtl::OUString
ElementConfig::format( SvStream
& rStream
, sal_Size
& nLength
) const
357 if( maName
.getLength() )
360 aRet
+= OUString( " = " );
365 case ECT_BYTE
: aRet
+= dump_byte( rStream
, nLength
); break;
366 case ECT_UINT
: aRet
+= dump_uint( rStream
, nLength
); break;
367 case ECT_UNISTRING
: aRet
+= dump_unistring( rStream
, nLength
); break;
368 case ETC_FLOAT
: aRet
+= dump_float( rStream
, nLength
); break;
370 default: aRet
+= dump_hex( rStream
, nLength
); break;
376 rtl::OUString
ElementConfig::dump_hex( SvStream
& rStream
, sal_Size
& nLength
)
379 OUString aOut
, aEmpty
;
380 OUString aHex
, aAscii
;
383 while( nLength
&& (rStream
.GetError() == 0) )
390 sprintf( buffer
, "%02x ", i
);
391 aHex
+= OUString::createFromAscii( buffer
);
396 aAscii
+= OUString( (sal_Unicode
) c
);
399 if( (nRow
== 16) || (nLength
==0) )
401 while( aHex
.getLength() < (16*3) )
402 aHex
+= OUString( " " );
405 aOut
+= OUString( "\n\r" );
418 rtl::OUString
ElementConfig::dump_byte( SvStream
& rStream
, sal_Size
& nLength
)
421 if( nLength
>= sizeof(sal_Char
) )
427 sprintf( buffer
, "%u", (int)c
);
428 aRet
+= OUString::createFromAscii( buffer
);
429 nLength
-= sizeof(sal_Char
);
435 rtl::OUString
ElementConfig::dump_uint( SvStream
& rStream
, sal_Size
& nLength
)
438 if( nLength
>= sizeof( sal_uInt32
) )
444 sprintf( buffer
, "%u", c
);
445 aRet
+= OUString::createFromAscii( buffer
);
446 nLength
-= sizeof( sal_uInt32
);
452 rtl::OUString
ElementConfig::dump_unistring( SvStream
& rStream
, sal_Size
& nLength
)
454 String aString
= SvxMSDffManager::MSDFFReadZString( rStream
, nLength
, sal_True
);
459 rtl::OUString
ElementConfig::dump_float( SvStream
& rStream
, sal_Size
& nLength
)
462 if( nLength
>= sizeof( float ) )
468 sprintf( buffer
, "%g", (double)c
);
469 aRet
+= OUString::createFromAscii( buffer
);
470 nLength
-= sizeof( float );
476 ///////////////////////////////////////////////////////////////////////
478 rtl::OUString
ElementConfigContainer::format( SvStream
& rStream
, sal_Size
& nLength
) const
482 if( getType() == ETC_CONTAINER
)
485 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
486 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
487 while( (aIter
!= aEnd
) && (nLength
> 0) )
489 aRet
+= (*aIter
++)->format( rStream
, nLength
);
490 if( (aIter
!= aEnd
) || (nLength
!= 0) )
491 aRet
+= OUString( "\n\r" );
495 aRet
+= ElementConfig::dump_hex( rStream
, nLength
);
500 if( aRet
.getLength() )
501 aRet
+= OUString( " = " );
506 case ECT_BYTE
: aValue
= dump_byte( rStream
, nLength
); break;
507 case ECT_UINT
: aValue
= dump_uint( rStream
, nLength
); break;
508 case ECT_UNISTRING
: aValue
= dump_unistring( rStream
, nLength
); break;
509 case ETC_FLOAT
: aValue
= dump_float( rStream
, nLength
); break;
511 default: aValue
= dump_hex( rStream
, nLength
); break;
514 if( aValue
.getLength() )
516 if( !maElementConfigList
.empty() )
518 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
519 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
520 while( (aIter
!= aEnd
) && (nLength
> 0) )
522 ElementValueConfig
* pValue
= dynamic_cast< ElementValueConfig
* >( (*aIter
++).get() );
523 if( pValue
&& pValue
->getValue() == aValue
)
525 aValue
= pValue
->getName();
533 aValue
= OUString( "<empty!?>" );
542 ///////////////////////////////////////////////////////////////////////
544 rtl::OUString
SwitchElementConfig::format( SvStream
& rStream
, sal_Size
& nLength
) const
550 case ECT_BYTE
: aValue
= dump_byte( rStream
, nLength
); break;
551 case ECT_UINT
: aValue
= dump_uint( rStream
, nLength
); break;
552 case ETC_FLOAT
: aValue
= dump_float( rStream
, nLength
); break;
553 case ECT_UNISTRING
: aValue
= dump_unistring( rStream
, nLength
); break;
556 if( aValue
.getLength() )
558 ElementConfigList::const_iterator
aIter( maElementConfigList
.begin() );
559 const ElementConfigList::const_iterator
aEnd( maElementConfigList
.end() );
560 while( (aIter
!= aEnd
) && (nLength
> 0) )
562 CaseElementConfig
* pCase
= dynamic_cast< CaseElementConfig
* >( (*aIter
++).get() );
563 if( pCase
&& pCase
->getValue() == aValue
)
564 return pCase
->format( rStream
, nLength
);
568 return ElementConfig::dump_hex( rStream
, nLength
);
571 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */