sync master with lastest vba changes
[ooovba.git] / stoc / source / registry_tdprovider / rdbtdp_tdenumeration.cxx
blobd77aef182932963a5c24a49ccdaacd1ad254ef70
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rdbtdp_tdenumeration.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 //=========================================================================
35 // Todo:
37 // - closeKey() calls (according to JSC not really needed because XRegistry
38 // implementation closes key in it's dtor.
40 //=========================================================================
41 #include <osl/diagnose.h>
42 #include <rtl/ustrbuf.hxx>
43 #include "com/sun/star/reflection/XPublished.hpp"
44 #include "cppuhelper/implbase1.hxx"
45 #include "registry/reader.hxx"
46 #include "registry/version.h"
47 #include "base.hxx"
48 #include "rdbtdp_tdenumeration.hxx"
50 using namespace com::sun::star;
52 namespace {
54 class IndividualConstantTypeDescriptionImpl:
55 public cppu::ImplInheritanceHelper1<
56 stoc_rdbtdp::ConstantTypeDescriptionImpl,
57 com::sun::star::reflection::XPublished >
59 public:
60 IndividualConstantTypeDescriptionImpl(
61 rtl::OUString const & name, com::sun::star::uno::Any const & value,
62 bool published):
63 cppu::ImplInheritanceHelper1<
64 stoc_rdbtdp::ConstantTypeDescriptionImpl,
65 com::sun::star::reflection::XPublished >(name, value),
66 m_published(published) {}
68 virtual sal_Bool SAL_CALL isPublished()
69 throw (::com::sun::star::uno::RuntimeException)
70 { return m_published; }
72 private:
73 bool m_published;
78 namespace stoc_rdbtdp
81 //=========================================================================
82 //=========================================================================
84 // TypeDescriptionEnumerationImpl Implementation.
86 //=========================================================================
87 //=========================================================================
89 // static
90 rtl::Reference< TypeDescriptionEnumerationImpl >
91 TypeDescriptionEnumerationImpl::createInstance(
92 const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
93 const rtl::OUString & rModuleName,
94 const uno::Sequence< uno::TypeClass > & rTypes,
95 reflection::TypeDescriptionSearchDepth eDepth,
96 const RegistryKeyList & rBaseKeys )
97 throw ( reflection::NoSuchTypeNameException,
98 reflection::InvalidTypeNameException,
99 uno::RuntimeException )
101 if ( rModuleName.getLength() == 0 )
103 // Enumeration for root requested.
104 return rtl::Reference< TypeDescriptionEnumerationImpl >(
105 new TypeDescriptionEnumerationImpl(
106 xTDMgr, rBaseKeys, rTypes, eDepth ) );
109 RegistryKeyList aModuleKeys;
111 rtl::OUString aKey( rModuleName.replace( '.', '/' ) );
113 bool bOpenKeySucceeded = false;
115 const RegistryKeyList::const_iterator end = rBaseKeys.end();
116 RegistryKeyList::const_iterator it = rBaseKeys.begin();
118 while ( it != end )
120 uno::Reference< registry::XRegistryKey > xKey;
123 xKey = (*it)->openKey( aKey );
124 if ( xKey.is() )
126 // closes key in it's dtor (which is
127 // called even in case of exceptions).
128 RegistryKeyCloser aCloser( xKey );
130 if ( xKey->isValid() )
132 bOpenKeySucceeded = true;
134 if ( xKey->getValueType()
135 == registry::RegistryValueType_BINARY )
137 uno::Sequence< sal_Int8 > aBytes(
138 xKey->getBinaryValue() );
140 typereg::Reader aReader(
141 aBytes.getConstArray(), aBytes.getLength(), false,
142 TYPEREG_VERSION_1);
144 rtl::OUString aName(
145 aReader.getTypeName().replace( '/', '.' ) );
147 if ( aReader.getTypeClass() == RT_TYPE_MODULE )
149 // Do not close xKey!
150 aCloser.reset();
152 aModuleKeys.push_back( xKey );
156 else
158 OSL_ENSURE(
159 sal_False,
160 "TypeDescriptionEnumerationImpl::createInstance "
161 "- Invalid registry key!" );
165 catch ( registry::InvalidRegistryException const & )
167 // openKey, getValueType, getBinaryValue
169 OSL_ENSURE( sal_False,
170 "TypeDescriptionEnumerationImpl::createInstance "
171 "- Caught InvalidRegistryException!" );
174 it++;
177 if ( !bOpenKeySucceeded )
178 throw reflection::NoSuchTypeNameException();
180 if ( aModuleKeys.size() == 0 )
181 throw reflection::InvalidTypeNameException();
183 return rtl::Reference< TypeDescriptionEnumerationImpl >(
184 new TypeDescriptionEnumerationImpl(
185 xTDMgr, aModuleKeys, rTypes, eDepth ) );
188 //=========================================================================
189 TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl(
190 const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
191 const RegistryKeyList & rModuleKeys,
192 const uno::Sequence< uno::TypeClass > & rTypes,
193 reflection::TypeDescriptionSearchDepth eDepth )
194 : m_aModuleKeys( rModuleKeys ),
195 m_aTypes( rTypes ),
196 m_eDepth( eDepth ),
197 m_xTDMgr( xTDMgr )
199 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
202 //=========================================================================
203 // virtual
204 TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl()
206 RegistryKeyList::const_iterator it = m_aModuleKeys.begin();
207 RegistryKeyList::const_iterator end = m_aModuleKeys.end();
209 @@@ in case we enumerate root and queryMore was never called, then
210 m_aModuleKeys contains open root keys which where passed from
211 tdprov and must not be closed by us.
213 while ( it != end )
217 if ( (*it)->isValid() )
218 (*it)->closeKey();
220 catch (...)
222 // No exceptions from dtors, please!
223 OSL_ENSURE( sal_False,
224 "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
225 "- Caught exception!" );
228 it++;
231 it = m_aCurrentModuleSubKeys.begin();
232 end = m_aCurrentModuleSubKeys.end();
233 while ( it != end )
237 if ( (*it)->isValid() )
238 (*it)->closeKey();
240 catch (Exception &)
242 // No exceptions from dtors, please!
243 OSL_ENSURE( sal_False,
244 "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
245 "- Caught exception!" );
248 it++;
251 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
254 //=========================================================================
256 // XEnumeration (base of XTypeDescriptionEnumeration) methods
258 //=========================================================================
260 // virtual
261 sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements()
262 throw ( uno::RuntimeException )
264 return queryMore();
267 //=========================================================================
268 // virtual
269 uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement()
270 throw ( container::NoSuchElementException,
271 lang::WrappedTargetException,
272 uno::RuntimeException )
274 return uno::Any( uno::makeAny( nextTypeDescription() ) );
277 //=========================================================================
279 // XTypeDescriptionEnumeration methods
281 //=========================================================================
283 // virtual
284 uno::Reference< reflection::XTypeDescription > SAL_CALL
285 TypeDescriptionEnumerationImpl::nextTypeDescription()
286 throw ( container::NoSuchElementException,
287 uno::RuntimeException )
289 uno::Reference< reflection::XTypeDescription > xTD( queryNext() );
291 if ( xTD.is() )
292 return xTD;
294 throw container::NoSuchElementException(
295 rtl::OUString::createFromAscii(
296 "No further elements in enumeration!" ),
297 static_cast< cppu::OWeakObject * >( this ) );
300 //=========================================================================
301 bool TypeDescriptionEnumerationImpl::match(
302 RTTypeClass eType1, uno::TypeClass eType2 )
304 switch ( eType1 )
306 case RT_TYPE_INTERFACE:
307 return eType2 == uno::TypeClass_INTERFACE;
309 case RT_TYPE_MODULE:
310 return eType2 == uno::TypeClass_MODULE;
312 case RT_TYPE_STRUCT:
313 return eType2 == uno::TypeClass_STRUCT;
315 case RT_TYPE_ENUM:
316 return eType2 == uno::TypeClass_ENUM;
318 case RT_TYPE_EXCEPTION:
319 return eType2 == uno::TypeClass_EXCEPTION;
321 case RT_TYPE_TYPEDEF:
322 return eType2 == uno::TypeClass_TYPEDEF;
324 case RT_TYPE_SERVICE:
325 return eType2 == uno::TypeClass_SERVICE;
327 case RT_TYPE_SINGLETON:
328 return eType2 == uno::TypeClass_SINGLETON;
330 case RT_TYPE_CONSTANTS:
331 return eType2 == uno::TypeClass_CONSTANTS;
333 case RT_TYPE_UNION:
334 return eType2 == uno::TypeClass_UNION;
336 default:
337 return false;
341 //=========================================================================
342 bool TypeDescriptionEnumerationImpl::queryMore()
344 osl::MutexGuard aGuard( m_aMutex );
346 for (;;)
348 if ( !m_aCurrentModuleSubKeys.empty() || !m_aTypeDescs.empty() )
350 // Okay, there is at least one more element.
351 return true;
354 if ( m_aModuleKeys.empty() )
356 // No module keys (therefore no elements) left.
357 return false;
360 // Note: m_aCurrentModuleSubKeys is always empty AND m_aModuleKeys is
361 // never empty when ariving here.
362 // ==> select new module key, fill m_aCurrentModuleSubKeys
364 uno::Sequence< uno::Reference< registry::XRegistryKey > > aKeys;
367 aKeys = m_aModuleKeys.front()->openKeys();
368 for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
370 uno::Reference< registry::XRegistryKey > xKey = aKeys[ n ];
372 // closes key in it's dtor (which is
373 // called even in case of exceptions).
374 RegistryKeyCloser aCloser( xKey );
378 if ( xKey->isValid() )
380 if ( xKey->getValueType()
381 == registry::RegistryValueType_BINARY )
383 bool bIncludeIt = (m_aTypes.getLength() == 0);
384 bool bNeedTypeClass =
385 ((m_aTypes.getLength() > 0) ||
386 (m_eDepth
387 == reflection::TypeDescriptionSearchDepth_INFINITE));
388 if ( bNeedTypeClass )
390 uno::Sequence< sal_Int8 > aBytes(
391 xKey->getBinaryValue() );
393 typereg::Reader aReader(
394 aBytes.getConstArray(), aBytes.getLength(),
395 false, TYPEREG_VERSION_1);
397 RTTypeClass eTypeClass = aReader.getTypeClass();
399 // Does key match requested types? Empty
400 // sequence means include all.
401 if ( m_aTypes.getLength() > 0 )
403 for ( sal_Int32 m = 0;
404 m < m_aTypes.getLength();
405 ++m )
407 if ( match(eTypeClass, m_aTypes[ m ]) )
409 bIncludeIt = true;
410 break;
415 if ( m_eDepth ==
416 reflection::TypeDescriptionSearchDepth_INFINITE )
418 if ( eTypeClass == RT_TYPE_MODULE )
420 // Do not close xKey!
421 aCloser.reset();
423 // Remember new module key.
424 m_aModuleKeys.push_back( xKey );
429 if ( bIncludeIt )
431 // Do not close xKey!
432 aCloser.reset();
434 m_aCurrentModuleSubKeys.push_back( xKey );
438 else
440 OSL_ENSURE( sal_False,
441 "TypeDescriptionEnumerationImpl::queryMore "
442 "- Invalid registry key!" );
446 catch ( registry::InvalidRegistryException const & )
448 // getValueType, getBinaryValue
450 OSL_ENSURE( sal_False,
451 "TypeDescriptionEnumerationImpl::queryMore "
452 "- Caught InvalidRegistryException!" );
454 // Don't stop iterating!
458 catch ( registry::InvalidRegistryException const & )
460 // openKeys
462 for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
466 aKeys[ n ]->closeKey();
468 catch ( registry::InvalidRegistryException const & )
470 OSL_ENSURE( sal_False,
471 "TypeDescriptionEnumerationImpl::queryMore "
472 "- Caught InvalidRegistryException!" );
477 /////////////////////////////////////////////////////////////////////
478 // Special handling for constants contained directly in module.
479 /////////////////////////////////////////////////////////////////////
481 // Constants requested?
482 bool bIncludeConstants = ( m_aTypes.getLength() == 0 );
483 if ( !bIncludeConstants )
485 for ( sal_Int32 m = 0; m < m_aTypes.getLength(); ++m )
487 if ( m_aTypes[ m ] == uno::TypeClass_CONSTANT )
489 bIncludeConstants = true;
490 break;
496 if ( bIncludeConstants )
498 if ( m_aModuleKeys.front()->getValueType()
499 == registry::RegistryValueType_BINARY )
503 uno::Sequence< sal_Int8 > aBytes(
504 m_aModuleKeys.front()->getBinaryValue() );
506 typereg::Reader aReader(
507 aBytes.getConstArray(), aBytes.getLength(), false,
508 TYPEREG_VERSION_1);
510 if ( aReader.getTypeClass() == RT_TYPE_MODULE )
512 sal_uInt16 nFields = aReader.getFieldCount();
513 while ( nFields-- )
515 rtl::OUStringBuffer aName(
516 aReader.getTypeName().replace( '/', '.' ) );
517 aName.appendAscii( "." );
518 aName.append( aReader.getFieldName( nFields ) );
520 uno::Any aValue(
521 getRTValue(
522 aReader.getFieldValue( nFields ) ) );
524 m_aTypeDescs.push_back(
525 new IndividualConstantTypeDescriptionImpl(
526 aName.makeStringAndClear(), aValue,
527 ( ( aReader.getFieldFlags( nFields )
528 & RT_ACCESS_PUBLISHED )
529 != 0 ) ) );
533 catch ( registry::InvalidRegistryException const & )
535 // getBinaryValue
537 OSL_ENSURE( sal_False,
538 "TypeDescriptionEnumerationImpl::queryMore "
539 "- Caught InvalidRegistryException!" );
544 /////////////////////////////////////////////////////////////////////
547 @@@ m_aModuleKeys.front() may have open sub keys (may be contained in
548 both m_aModuleKeys and m_aCurrentModuleSubKeys)!
552 m_aModuleKeys.front()->closeKey();
554 catch ( registry::InvalidRegistryException const & )
556 OSL_ENSURE( sal_False,
557 "TypeDescriptionEnumerationImpl::queryMore "
558 "- Caught InvalidRegistryException!" );
561 // We're done with this module key, even if there were errors.
562 m_aModuleKeys.pop_front();
565 // unreachable
568 //=========================================================================
569 uno::Reference< reflection::XTypeDescription >
570 TypeDescriptionEnumerationImpl::queryNext()
572 osl::MutexGuard aGuard( m_aMutex );
574 for (;;)
576 if ( !queryMore() )
577 return uno::Reference< reflection::XTypeDescription >();
579 uno::Reference< reflection::XTypeDescription > xTD;
581 if ( !m_aTypeDescs.empty() )
583 xTD = m_aTypeDescs.front();
584 m_aTypeDescs.pop_front();
585 return xTD;
588 // Note: xKey is already opened.
589 uno::Reference< registry::XRegistryKey >
590 xKey( m_aCurrentModuleSubKeys.front() );
592 @@@ xKey may still be contained in m_aModuleKeys, too
594 // closes key in it's dtor (which is
595 // called even in case of exceptions).
596 RegistryKeyCloser aCloser( xKey );
601 if ( xKey->isValid() )
603 if ( xKey->getValueType()
604 == registry::RegistryValueType_BINARY )
606 uno::Sequence< sal_Int8 > aBytes(
607 xKey->getBinaryValue() );
609 xTD = createTypeDescription( aBytes,
610 m_xTDMgr,
611 false );
612 OSL_ENSURE( xTD.is(),
613 "TypeDescriptionEnumerationImpl::queryNext "
614 "- No XTypeDescription created!" );
617 else
619 OSL_ENSURE( sal_False,
620 "TypeDescriptionEnumerationImpl::queryNext "
621 "- Invalid registry key!" );
625 catch ( registry::InvalidRegistryException const & )
627 // getValueType, getBinaryValue
629 OSL_ENSURE( sal_False,
630 "TypeDescriptionEnumerationImpl::queryNext "
631 "- Caught InvalidRegistryException!" );
634 // We're done with this key, even if there were errors.
635 m_aCurrentModuleSubKeys.pop_front();
637 if ( xTD.is() )
638 return xTD;
640 // next try...
642 } // for (;;)
645 } // namespace stoc_rdbtdp