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