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