xref: /AOO41X/main/xmlscript/source/xml_helper/xml_impctx.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmlscript.hxx"
30 
31 #include "osl/diagnose.h"
32 #include "osl/mutex.hxx"
33 #include "rtl/ustrbuf.hxx"
34 #include "cppuhelper/factory.hxx"
35 #include "cppuhelper/implementationentry.hxx"
36 #include "cppuhelper/implbase1.hxx"
37 #include "cppuhelper/implbase3.hxx"
38 #include "xmlscript/xml_import.hxx"
39 
40 #include "com/sun/star/xml/input/XAttributes.hpp"
41 #include "com/sun/star/lang/XInitialization.hpp"
42 #include "com/sun/star/uno/XComponentContext.hpp"
43 
44 #include <vector>
45 #include <hash_map>
46 
47 #include <memory>
48 
49 
50 using namespace ::rtl;
51 using namespace ::osl;
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 
55 namespace xmlscript
56 {
57 
58 const sal_Int32 UID_UNKNOWN = -1;
59 
60 Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl()
61 {
62     OUString name( RTL_CONSTASCII_USTRINGPARAM(
63                        "com.sun.star.xml.input.SaxDocumentHandler") );
64     return Sequence< OUString >( &name, 1 );
65 }
66 
67 OUString getImplementationName_DocumentHandlerImpl()
68 {
69     return OUString( RTL_CONSTASCII_USTRINGPARAM(
70                          "com.sun.star.comp.xml.input.SaxDocumentHandler") );
71 }
72 
73 typedef ::std::hash_map< OUString, sal_Int32, OUStringHash > t_OUString2LongMap;
74 typedef ::std::hash_map< sal_Int32, OUString > t_Long2OUStringMap;
75 
76 struct PrefixEntry
77 {
78     ::std::vector< sal_Int32 > m_Uids;
79 
80     inline PrefixEntry() SAL_THROW( () )
81         { m_Uids.reserve( 4 ); }
82 };
83 
84 typedef ::std::hash_map<
85     OUString, PrefixEntry *, OUStringHash > t_OUString2PrefixMap;
86 
87 struct ElementEntry
88 {
89     Reference< xml::input::XElement > m_xElement;
90     ::std::vector< OUString > m_prefixes;
91 
92     inline ElementEntry()
93         { m_prefixes.reserve( 2 ); }
94 };
95 
96 typedef ::std::vector< ElementEntry * > t_ElementVector;
97 
98 class ExtendedAttributes;
99 
100 //==============================================================================
101 struct MGuard
102 {
103     Mutex * m_pMutex;
104     explicit MGuard( Mutex * pMutex )
105         : m_pMutex( pMutex )
106         { if (m_pMutex) m_pMutex->acquire(); }
107     ~MGuard() throw ()
108         { if (m_pMutex) m_pMutex->release(); }
109 };
110 
111 //==============================================================================
112 class DocumentHandlerImpl :
113     public ::cppu::WeakImplHelper3< xml::sax::XDocumentHandler,
114                                     xml::input::XNamespaceMapping,
115                                     lang::XInitialization >
116 {
117     friend class ExtendedAttributes;
118 
119     Reference< xml::input::XRoot > m_xRoot;
120 
121     t_OUString2LongMap m_URI2Uid;
122     sal_Int32 m_uid_count;
123 
124     OUString m_sXMLNS_PREFIX_UNKNOWN;
125     OUString m_sXMLNS;
126 
127     sal_Int32 m_nLastURI_lookup;
128     OUString m_aLastURI_lookup;
129 
130     t_OUString2PrefixMap m_prefixes;
131     sal_Int32 m_nLastPrefix_lookup;
132     OUString m_aLastPrefix_lookup;
133 
134     t_ElementVector m_elements;
135     sal_Int32 m_nSkipElements;
136 
137     Mutex * m_pMutex;
138 
139     inline Reference< xml::input::XElement > getCurrentElement() const;
140 
141     inline sal_Int32 getUidByURI( OUString const & rURI );
142     inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
143 
144     inline void pushPrefix(
145         OUString const & rPrefix, OUString const & rURI );
146     inline void popPrefix( OUString const & rPrefix );
147 
148     inline void getElementName(
149         OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
150 
151 public:
152     DocumentHandlerImpl(
153         Reference< xml::input::XRoot > const & xRoot,
154         bool bSingleThreadedUse );
155     virtual ~DocumentHandlerImpl() throw ();
156 
157     // XServiceInfo
158     virtual OUString SAL_CALL getImplementationName()
159         throw (RuntimeException);
160     virtual sal_Bool SAL_CALL supportsService(
161         OUString const & servicename )
162         throw (RuntimeException);
163     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
164         throw (RuntimeException);
165 
166     // XInitialization
167     virtual void SAL_CALL initialize(
168         Sequence< Any > const & arguments )
169         throw (Exception);
170 
171     // XDocumentHandler
172     virtual void SAL_CALL startDocument()
173         throw (xml::sax::SAXException, RuntimeException);
174     virtual void SAL_CALL endDocument()
175         throw (xml::sax::SAXException, RuntimeException);
176     virtual void SAL_CALL startElement(
177         OUString const & rQElementName,
178         Reference< xml::sax::XAttributeList > const & xAttribs )
179         throw (xml::sax::SAXException, RuntimeException);
180     virtual void SAL_CALL endElement(
181         OUString const & rQElementName )
182         throw (xml::sax::SAXException, RuntimeException);
183     virtual void SAL_CALL characters(
184         OUString const & rChars )
185         throw (xml::sax::SAXException, RuntimeException);
186     virtual void SAL_CALL ignorableWhitespace(
187         OUString const & rWhitespaces )
188         throw (xml::sax::SAXException, RuntimeException);
189     virtual void SAL_CALL processingInstruction(
190         OUString const & rTarget, OUString const & rData )
191         throw (xml::sax::SAXException, RuntimeException);
192     virtual void SAL_CALL setDocumentLocator(
193         Reference< xml::sax::XLocator > const & xLocator )
194         throw (xml::sax::SAXException, RuntimeException);
195 
196     // XNamespaceMapping
197     virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri )
198         throw (RuntimeException);
199     virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid )
200         throw (container::NoSuchElementException, RuntimeException);
201 };
202 
203 //______________________________________________________________________________
204 DocumentHandlerImpl::DocumentHandlerImpl(
205     Reference< xml::input::XRoot > const & xRoot,
206     bool bSingleThreadedUse )
207     : m_xRoot( xRoot ),
208       m_uid_count( 0 ),
209       m_sXMLNS_PREFIX_UNKNOWN(
210           RTL_CONSTASCII_USTRINGPARAM("<<< unknown prefix >>>") ),
211       m_sXMLNS( RTL_CONSTASCII_USTRINGPARAM("xmlns") ),
212       m_nLastURI_lookup( UID_UNKNOWN ),
213       m_aLastURI_lookup( RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ),
214       m_nLastPrefix_lookup( UID_UNKNOWN ),
215       m_aLastPrefix_lookup(
216           RTL_CONSTASCII_USTRINGPARAM("<<< unknown URI >>>") ),
217       m_nSkipElements( 0 ),
218       m_pMutex( 0 )
219 {
220     m_elements.reserve( 10 );
221 
222     if (! bSingleThreadedUse)
223         m_pMutex = new Mutex();
224 }
225 
226 //______________________________________________________________________________
227 DocumentHandlerImpl::~DocumentHandlerImpl() throw ()
228 {
229     if (m_pMutex != 0)
230     {
231         delete m_pMutex;
232 #if OSL_DEBUG_LEVEL == 0
233         m_pMutex = 0;
234 #endif
235     }
236 }
237 
238 //______________________________________________________________________________
239 inline Reference< xml::input::XElement >
240 DocumentHandlerImpl::getCurrentElement() const
241 {
242     MGuard aGuard( m_pMutex );
243     if (m_elements.empty())
244         return Reference< xml::input::XElement >();
245     else
246         return m_elements.back()->m_xElement;
247 }
248 
249 //______________________________________________________________________________
250 inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
251 {
252     MGuard guard( m_pMutex );
253     if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
254     {
255         t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
256         if (iFind != m_URI2Uid.end()) // id found
257         {
258             m_nLastURI_lookup = iFind->second;
259             m_aLastURI_lookup = rURI;
260         }
261         else
262         {
263             m_nLastURI_lookup = m_uid_count;
264             ++m_uid_count;
265             m_URI2Uid[ rURI ] = m_nLastURI_lookup;
266             m_aLastURI_lookup = rURI;
267         }
268     }
269     return m_nLastURI_lookup;
270 }
271 
272 //______________________________________________________________________________
273 inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
274     OUString const & rPrefix )
275 {
276     // commonly the last added prefix is used often for several tags...
277     // good guess
278     if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
279     {
280         t_OUString2PrefixMap::const_iterator iFind(
281             m_prefixes.find( rPrefix ) );
282         if (iFind != m_prefixes.end())
283         {
284             const PrefixEntry & rPrefixEntry = *iFind->second;
285             OSL_ASSERT( ! rPrefixEntry.m_Uids.empty() );
286             m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
287             m_aLastPrefix_lookup = rPrefix;
288         }
289         else
290         {
291             m_nLastPrefix_lookup = UID_UNKNOWN;
292             m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
293         }
294     }
295     return m_nLastPrefix_lookup;
296 }
297 
298 //______________________________________________________________________________
299 inline void DocumentHandlerImpl::pushPrefix(
300     OUString const & rPrefix, OUString const & rURI )
301 {
302     // lookup id for URI
303     sal_Int32 nUid = getUidByURI( rURI );
304 
305     // mark prefix with id
306     t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
307     if (iFind == m_prefixes.end()) // unused prefix
308     {
309         PrefixEntry * pEntry = new PrefixEntry();
310         pEntry->m_Uids.push_back( nUid ); // latest id for prefix
311         m_prefixes[ rPrefix ] = pEntry;
312     }
313     else
314     {
315         PrefixEntry * pEntry = iFind->second;
316         OSL_ASSERT( ! pEntry->m_Uids.empty() );
317         pEntry->m_Uids.push_back( nUid );
318     }
319 
320     m_aLastPrefix_lookup = rPrefix;
321     m_nLastPrefix_lookup = nUid;
322 }
323 
324 //______________________________________________________________________________
325 inline void DocumentHandlerImpl::popPrefix(
326     OUString const & rPrefix )
327 {
328     t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
329     if (iFind != m_prefixes.end()) // unused prefix
330     {
331         PrefixEntry * pEntry = iFind->second;
332         pEntry->m_Uids.pop_back(); // pop last id for prefix
333         if (pEntry->m_Uids.empty()) // erase prefix key
334         {
335             m_prefixes.erase( iFind );
336             delete pEntry;
337         }
338     }
339 
340     m_nLastPrefix_lookup = UID_UNKNOWN;
341     m_aLastPrefix_lookup = m_sXMLNS_PREFIX_UNKNOWN;
342 }
343 
344 //______________________________________________________________________________
345 inline void DocumentHandlerImpl::getElementName(
346     OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
347 {
348     sal_Int32 nColonPos = rQName.indexOf( (sal_Unicode)':' );
349     *pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
350     *pUid = getUidByPrefix(
351         nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
352 }
353 
354 
355 //==============================================================================
356 class ExtendedAttributes :
357     public ::cppu::WeakImplHelper1< xml::input::XAttributes >
358 {
359     sal_Int32 m_nAttributes;
360     sal_Int32 * m_pUids;
361     OUString * m_pPrefixes;
362     OUString * m_pLocalNames;
363     OUString * m_pQNames;
364     OUString * m_pValues;
365 
366     DocumentHandlerImpl * m_pHandler;
367 
368 public:
369     inline ExtendedAttributes(
370         sal_Int32 nAttributes,
371         sal_Int32 * pUids, OUString * pPrefixes,
372         OUString * pLocalNames, OUString * pQNames,
373         Reference< xml::sax::XAttributeList > const & xAttributeList,
374         DocumentHandlerImpl * pHandler );
375     virtual ~ExtendedAttributes() throw ();
376 
377     // XAttributes
378     virtual sal_Int32 SAL_CALL getLength()
379         throw (RuntimeException);
380     virtual sal_Int32 SAL_CALL getIndexByQName(
381         OUString const & rQName )
382         throw (RuntimeException);
383     virtual sal_Int32 SAL_CALL getIndexByUidName(
384         sal_Int32 nUid, OUString const & rLocalName )
385         throw (RuntimeException);
386     virtual OUString SAL_CALL getQNameByIndex(
387         sal_Int32 nIndex )
388         throw (RuntimeException);
389     virtual sal_Int32 SAL_CALL getUidByIndex(
390         sal_Int32 nIndex )
391         throw (RuntimeException);
392     virtual OUString SAL_CALL getLocalNameByIndex(
393         sal_Int32 nIndex )
394         throw (RuntimeException);
395     virtual OUString SAL_CALL getValueByIndex(
396         sal_Int32 nIndex )
397         throw (RuntimeException);
398     virtual OUString SAL_CALL getValueByUidName(
399         sal_Int32 nUid, OUString const & rLocalName )
400         throw (RuntimeException);
401     virtual OUString SAL_CALL getTypeByIndex(
402         sal_Int32 nIndex )
403         throw (RuntimeException);
404 };
405 
406 //______________________________________________________________________________
407 inline ExtendedAttributes::ExtendedAttributes(
408     sal_Int32 nAttributes,
409     sal_Int32 * pUids, OUString * pPrefixes,
410     OUString * pLocalNames, OUString * pQNames,
411     Reference< xml::sax::XAttributeList > const & xAttributeList,
412     DocumentHandlerImpl * pHandler )
413     : m_nAttributes( nAttributes )
414     , m_pUids( pUids )
415     , m_pPrefixes( pPrefixes )
416     , m_pLocalNames( pLocalNames )
417     , m_pQNames( pQNames )
418     , m_pValues( new OUString[ nAttributes ] )
419     , m_pHandler( pHandler )
420 {
421     m_pHandler->acquire();
422 
423     for ( sal_Int16 nPos = 0; nPos < nAttributes; ++nPos )
424     {
425         m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
426     }
427 }
428 
429 //______________________________________________________________________________
430 ExtendedAttributes::~ExtendedAttributes() throw ()
431 {
432     m_pHandler->release();
433 
434     delete [] m_pUids;
435     delete [] m_pPrefixes;
436     delete [] m_pLocalNames;
437     delete [] m_pQNames;
438     delete [] m_pValues;
439 }
440 
441 
442 //##############################################################################
443 
444 // XServiceInfo
445 
446 //______________________________________________________________________________
447 OUString DocumentHandlerImpl::getImplementationName()
448     throw (RuntimeException)
449 {
450     return getImplementationName_DocumentHandlerImpl();
451 }
452 
453 //______________________________________________________________________________
454 sal_Bool DocumentHandlerImpl::supportsService(
455     OUString const & servicename )
456     throw (RuntimeException)
457 {
458     Sequence< OUString > names( getSupportedServiceNames_DocumentHandlerImpl() );
459     for ( sal_Int32 nPos = names.getLength(); nPos--; )
460     {
461         if (names[ nPos ].equals( servicename ))
462             return sal_True;
463     }
464     return sal_False;
465 }
466 
467 //______________________________________________________________________________
468 Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
469     throw (RuntimeException)
470 {
471     return getSupportedServiceNames_DocumentHandlerImpl();
472 }
473 
474 // XInitialization
475 
476 //______________________________________________________________________________
477 void DocumentHandlerImpl::initialize(
478     Sequence< Any > const & arguments )
479     throw (Exception)
480 {
481     MGuard guard( m_pMutex );
482     Reference< xml::input::XRoot > xRoot;
483     if (arguments.getLength() == 1 &&
484         (arguments[ 0 ] >>= xRoot) &&
485         xRoot.is())
486     {
487         m_xRoot = xRoot;
488     }
489     else
490     {
491         throw RuntimeException(
492             OUString( RTL_CONSTASCII_USTRINGPARAM(
493                           "missing root instance!") ),
494             Reference< XInterface >() );
495     }
496 }
497 
498 
499 // XNamespaceMapping
500 
501 //______________________________________________________________________________
502 sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
503     throw (RuntimeException)
504 {
505     sal_Int32 uid = getUidByURI( Uri );
506     OSL_ASSERT( uid != UID_UNKNOWN );
507     return uid;
508 }
509 
510 //______________________________________________________________________________
511 OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
512     throw (container::NoSuchElementException, RuntimeException)
513 {
514     MGuard guard( m_pMutex );
515     t_OUString2LongMap::const_iterator iPos( m_URI2Uid.begin() );
516     t_OUString2LongMap::const_iterator const iEnd( m_URI2Uid.end() );
517     for ( ; iPos != iEnd; ++iPos )
518     {
519         if (iPos->second == Uid)
520             return iPos->first;
521     }
522     throw container::NoSuchElementException(
523         OUString( RTL_CONSTASCII_USTRINGPARAM("no such xmlns uid!") ),
524         static_cast< OWeakObject * >(this) );
525 }
526 
527 
528 // XDocumentHandler
529 
530 //______________________________________________________________________________
531 void DocumentHandlerImpl::startDocument()
532     throw (xml::sax::SAXException, RuntimeException)
533 {
534     m_xRoot->startDocument(
535         static_cast< xml::input::XNamespaceMapping * >( this ) );
536 }
537 
538 //______________________________________________________________________________
539 void DocumentHandlerImpl::endDocument()
540     throw (xml::sax::SAXException, RuntimeException)
541 {
542     m_xRoot->endDocument();
543 }
544 
545 //______________________________________________________________________________
546 void DocumentHandlerImpl::startElement(
547     OUString const & rQElementName,
548     Reference< xml::sax::XAttributeList > const & xAttribs )
549     throw (xml::sax::SAXException, RuntimeException)
550 {
551     Reference< xml::input::XElement > xCurrentElement;
552     Reference< xml::input::XAttributes > xAttributes;
553     sal_Int32 nUid;
554     OUString aLocalName;
555     ::std::auto_ptr< ElementEntry > elementEntry( new ElementEntry );
556 
557     { // guard start:
558     MGuard aGuard( m_pMutex );
559     // currently skipping elements and waiting for end tags?
560     if (m_nSkipElements > 0)
561     {
562         ++m_nSkipElements; // wait for another end tag
563 #if OSL_DEBUG_LEVEL > 1
564         OString aQName(
565             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
566         OSL_TRACE( "### no context given on createChildElement() "
567                    "=> ignoring element \"%s\" ...", aQName.getStr() );
568 #endif
569         return;
570     }
571 
572     sal_Int16 nAttribs = xAttribs->getLength();
573 
574     // save all namespace ids
575     sal_Int32 * pUids = new sal_Int32[ nAttribs ];
576     OUString * pPrefixes = new OUString[ nAttribs ];
577     OUString * pLocalNames = new OUString[ nAttribs ];
578     OUString * pQNames = new OUString[ nAttribs ];
579 
580     // first recognize all xmlns attributes
581     sal_Int16 nPos;
582     for ( nPos = 0; nPos < nAttribs; ++nPos )
583     {
584         // mark attribute to be collected further
585         // on with attribute's uid and current prefix
586         pUids[ nPos ] = 0; // modified
587 
588         pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
589         OUString const & rQAttributeName = pQNames[ nPos ];
590 
591         if (rQAttributeName.compareTo( m_sXMLNS, 5 ) == 0)
592         {
593             if (rQAttributeName.getLength() == 5) // set default namespace
594             {
595                 OUString aDefNamespacePrefix;
596                 pushPrefix(
597                     aDefNamespacePrefix,
598                     xAttribs->getValueByIndex( nPos ) );
599                 elementEntry->m_prefixes.push_back( aDefNamespacePrefix );
600                 pUids[ nPos ]          = UID_UNKNOWN;
601                 pPrefixes[ nPos ]      = m_sXMLNS;
602                 pLocalNames[ nPos ]    = aDefNamespacePrefix;
603             }
604             else if ((sal_Unicode)':' == rQAttributeName[ 5 ]) // set prefix
605             {
606                 OUString aPrefix( rQAttributeName.copy( 6 ) );
607                 pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
608                 elementEntry->m_prefixes.push_back( aPrefix );
609                 pUids[ nPos ]          = UID_UNKNOWN;
610                 pPrefixes[ nPos ]      = m_sXMLNS;
611                 pLocalNames[ nPos ]    = aPrefix;
612             }
613             // else just a name starting with xmlns, but no prefix
614         }
615     }
616 
617     // now read out attribute prefixes (all namespace prefixes have been set)
618     for ( nPos = 0; nPos < nAttribs; ++nPos )
619     {
620         if (pUids[ nPos ] >= 0) // no xmlns: attribute
621         {
622             OUString const & rQAttributeName = pQNames[ nPos ];
623             OSL_ENSURE(
624                 rQAttributeName.compareToAscii(
625                     RTL_CONSTASCII_STRINGPARAM("xmlns:") ) != 0,
626                 "### unexpected xmlns!" );
627 
628             // collect attribute's uid and current prefix
629             sal_Int32 nColonPos = rQAttributeName.indexOf( (sal_Unicode) ':' );
630             if (nColonPos >= 0)
631             {
632                 pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
633                 pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
634             }
635             else
636             {
637                 pPrefixes[ nPos ] = OUString();
638                 pLocalNames[ nPos ] = rQAttributeName;
639                 // leave local names unmodified
640             }
641             pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
642         }
643     }
644     // ownership of arrays belongs to attribute list
645     xAttributes = static_cast< xml::input::XAttributes * >(
646         new ExtendedAttributes(
647             nAttribs, pUids, pPrefixes, pLocalNames, pQNames,
648             xAttribs, this ) );
649 
650     getElementName( rQElementName, &nUid, &aLocalName );
651 
652     // create new child context and append to list
653     if (! m_elements.empty())
654         xCurrentElement = m_elements.back()->m_xElement;
655     } // :guard end
656 
657     if (xCurrentElement.is())
658     {
659         elementEntry->m_xElement =
660             xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
661     }
662     else
663     {
664         elementEntry->m_xElement =
665             m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
666     }
667 
668     {
669     MGuard aGuard( m_pMutex );
670     if (elementEntry->m_xElement.is())
671     {
672         m_elements.push_back( elementEntry.release() );
673     }
674     else
675     {
676         ++m_nSkipElements;
677 #if OSL_DEBUG_LEVEL > 1
678         OString aQName(
679             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
680         OSL_TRACE(
681             "### no context given on createChildElement() => "
682             "ignoring element \"%s\" ...", aQName.getStr() );
683 #endif
684     }
685     }
686 }
687 
688 //______________________________________________________________________________
689 void DocumentHandlerImpl::endElement(
690     OUString const & rQElementName )
691     throw (xml::sax::SAXException, RuntimeException)
692 {
693     Reference< xml::input::XElement > xCurrentElement;
694     {
695     MGuard aGuard( m_pMutex );
696     if (m_nSkipElements)
697     {
698         --m_nSkipElements;
699 #if OSL_DEBUG_LEVEL > 1
700         OString aQName(
701             OUStringToOString( rQElementName, RTL_TEXTENCODING_ASCII_US ) );
702         OSL_TRACE( "### received endElement() for \"%s\".", aQName.getStr() );
703 #endif
704         static_cast<void>(rQElementName);
705         return;
706     }
707 
708     // popping context
709     OSL_ASSERT( ! m_elements.empty() );
710     ElementEntry * pEntry = m_elements.back();
711     xCurrentElement = pEntry->m_xElement;
712 
713 #if OSL_DEBUG_LEVEL > 0
714     sal_Int32 nUid;
715     OUString aLocalName;
716     getElementName( rQElementName, &nUid, &aLocalName );
717     OSL_ASSERT( xCurrentElement->getLocalName() == aLocalName );
718     OSL_ASSERT( xCurrentElement->getUid() == nUid );
719 #endif
720 
721     // pop prefixes
722     for ( sal_Int32 nPos = pEntry->m_prefixes.size(); nPos--; )
723     {
724         popPrefix( pEntry->m_prefixes[ nPos ] );
725     }
726     m_elements.pop_back();
727     delete pEntry;
728     }
729     xCurrentElement->endElement();
730 }
731 
732 //______________________________________________________________________________
733 void DocumentHandlerImpl::characters( OUString const & rChars )
734     throw (xml::sax::SAXException, RuntimeException)
735 {
736     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
737     if (xCurrentElement.is())
738         xCurrentElement->characters( rChars );
739 }
740 
741 //______________________________________________________________________________
742 void DocumentHandlerImpl::ignorableWhitespace(
743     OUString const & rWhitespaces )
744     throw (xml::sax::SAXException, RuntimeException)
745 {
746     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
747     if (xCurrentElement.is())
748         xCurrentElement->ignorableWhitespace( rWhitespaces );
749 }
750 
751 //______________________________________________________________________________
752 void DocumentHandlerImpl::processingInstruction(
753     OUString const & rTarget, OUString const & rData )
754     throw (xml::sax::SAXException, RuntimeException)
755 {
756     Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
757     if (xCurrentElement.is())
758         xCurrentElement->processingInstruction( rTarget, rData );
759     else
760         m_xRoot->processingInstruction( rTarget, rData );
761 }
762 
763 //______________________________________________________________________________
764 void DocumentHandlerImpl::setDocumentLocator(
765     Reference< xml::sax::XLocator > const & xLocator )
766     throw (xml::sax::SAXException, RuntimeException)
767 {
768     m_xRoot->setDocumentLocator( xLocator );
769 }
770 
771 //##############################################################################
772 
773 // XAttributes
774 
775 //______________________________________________________________________________
776 sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
777     throw (RuntimeException)
778 {
779     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
780     {
781         if (m_pQNames[ nPos ].equals( rQName ))
782         {
783             return nPos;
784         }
785     }
786     return -1;
787 }
788 
789 //______________________________________________________________________________
790 sal_Int32 ExtendedAttributes::getLength()
791     throw (RuntimeException)
792 {
793     return m_nAttributes;
794 }
795 
796 //______________________________________________________________________________
797 OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
798     throw (RuntimeException)
799 {
800     if (nIndex < m_nAttributes)
801         return m_pLocalNames[ nIndex ];
802     else
803         return OUString();
804 }
805 
806 //______________________________________________________________________________
807 OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
808     throw (RuntimeException)
809 {
810     if (nIndex < m_nAttributes)
811         return m_pQNames[ nIndex ];
812     else
813         return OUString();
814 }
815 
816 //______________________________________________________________________________
817 OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
818     throw (RuntimeException)
819 {
820     static_cast<void>(nIndex);
821     OSL_ASSERT( nIndex < m_nAttributes );
822     return OUString(); // unsupported
823 }
824 
825 //______________________________________________________________________________
826 OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
827     throw (RuntimeException)
828 {
829     if (nIndex < m_nAttributes)
830         return m_pValues[ nIndex ];
831     else
832         return OUString();
833 }
834 
835 //______________________________________________________________________________
836 sal_Int32 ExtendedAttributes::getIndexByUidName(
837     sal_Int32 nUid, OUString const & rLocalName )
838     throw (RuntimeException)
839 {
840     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
841     {
842         if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
843         {
844             return nPos;
845         }
846     }
847     return -1;
848 }
849 
850 //______________________________________________________________________________
851 sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
852     throw (RuntimeException)
853 {
854     if (nIndex < m_nAttributes)
855         return m_pUids[ nIndex ];
856     else
857         return -1;
858 }
859 
860 //______________________________________________________________________________
861 OUString ExtendedAttributes::getValueByUidName(
862     sal_Int32 nUid, OUString const & rLocalName )
863     throw (RuntimeException)
864 {
865     for ( sal_Int32 nPos = m_nAttributes; nPos--; )
866     {
867         if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
868         {
869             return m_pValues[ nPos ];
870         }
871     }
872     return OUString();
873 }
874 
875 
876 //##############################################################################
877 
878 
879 //==============================================================================
880 Reference< xml::sax::XDocumentHandler > SAL_CALL createDocumentHandler(
881     Reference< xml::input::XRoot > const & xRoot,
882     bool bSingleThreadedUse )
883     SAL_THROW( () )
884 {
885     OSL_ASSERT( xRoot.is() );
886     if (xRoot.is())
887     {
888         return static_cast< xml::sax::XDocumentHandler * >(
889             new DocumentHandlerImpl( xRoot, bSingleThreadedUse ) );
890     }
891     return Reference< xml::sax::XDocumentHandler >();
892 }
893 
894 //------------------------------------------------------------------------------
895 Reference< XInterface > SAL_CALL create_DocumentHandlerImpl(
896     Reference< XComponentContext > const & )
897     SAL_THROW( (Exception) )
898 {
899     return static_cast< ::cppu::OWeakObject * >(
900         new DocumentHandlerImpl(
901             Reference< xml::input::XRoot >(), false /* mt use */ ) );
902 }
903 
904 }
905