1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26
27 //=========================================================================
28 // Todo:
29 //
30 // - closeKey() calls (according to JSC not really needed because XRegistry
31 // implementation closes key in it's dtor.
32 //
33 //=========================================================================
34 #include <osl/diagnose.h>
35 #include <rtl/ustrbuf.hxx>
36 #include "com/sun/star/reflection/XPublished.hpp"
37 #include "cppuhelper/implbase1.hxx"
38 #include "registry/reader.hxx"
39 #include "registry/version.h"
40 #include "base.hxx"
41 #include "rdbtdp_tdenumeration.hxx"
42
43 using namespace com::sun::star;
44
45 namespace {
46
47 class IndividualConstantTypeDescriptionImpl:
48 public cppu::ImplInheritanceHelper1<
49 stoc_rdbtdp::ConstantTypeDescriptionImpl,
50 com::sun::star::reflection::XPublished >
51 {
52 public:
IndividualConstantTypeDescriptionImpl(rtl::OUString const & name,com::sun::star::uno::Any const & value,bool published)53 IndividualConstantTypeDescriptionImpl(
54 rtl::OUString const & name, com::sun::star::uno::Any const & value,
55 bool published):
56 cppu::ImplInheritanceHelper1<
57 stoc_rdbtdp::ConstantTypeDescriptionImpl,
58 com::sun::star::reflection::XPublished >(name, value),
59 m_published(published) {}
60
isPublished()61 virtual sal_Bool SAL_CALL isPublished()
62 throw (::com::sun::star::uno::RuntimeException)
63 { return m_published; }
64
65 private:
66 bool m_published;
67 };
68
69 }
70
71 namespace stoc_rdbtdp
72 {
73
74 //=========================================================================
75 //=========================================================================
76 //
77 // TypeDescriptionEnumerationImpl Implementation.
78 //
79 //=========================================================================
80 //=========================================================================
81
82 // static
83 rtl::Reference< TypeDescriptionEnumerationImpl >
createInstance(const uno::Reference<container::XHierarchicalNameAccess> & xTDMgr,const rtl::OUString & rModuleName,const uno::Sequence<uno::TypeClass> & rTypes,reflection::TypeDescriptionSearchDepth eDepth,const RegistryKeyList & rBaseKeys)84 TypeDescriptionEnumerationImpl::createInstance(
85 const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
86 const rtl::OUString & rModuleName,
87 const uno::Sequence< uno::TypeClass > & rTypes,
88 reflection::TypeDescriptionSearchDepth eDepth,
89 const RegistryKeyList & rBaseKeys )
90 throw ( reflection::NoSuchTypeNameException,
91 reflection::InvalidTypeNameException,
92 uno::RuntimeException )
93 {
94 if ( rModuleName.getLength() == 0 )
95 {
96 // Enumeration for root requested.
97 return rtl::Reference< TypeDescriptionEnumerationImpl >(
98 new TypeDescriptionEnumerationImpl(
99 xTDMgr, rBaseKeys, rTypes, eDepth ) );
100 }
101
102 RegistryKeyList aModuleKeys;
103
104 rtl::OUString aKey( rModuleName.replace( '.', '/' ) );
105
106 bool bOpenKeySucceeded = false;
107
108 const RegistryKeyList::const_iterator end = rBaseKeys.end();
109 RegistryKeyList::const_iterator it = rBaseKeys.begin();
110
111 while ( it != end )
112 {
113 uno::Reference< registry::XRegistryKey > xKey;
114 try
115 {
116 xKey = (*it)->openKey( aKey );
117 if ( xKey.is() )
118 {
119 // closes key in it's dtor (which is
120 // called even in case of exceptions).
121 RegistryKeyCloser aCloser( xKey );
122
123 if ( xKey->isValid() )
124 {
125 bOpenKeySucceeded = true;
126
127 if ( xKey->getValueType()
128 == registry::RegistryValueType_BINARY )
129 {
130 uno::Sequence< sal_Int8 > aBytes(
131 xKey->getBinaryValue() );
132
133 typereg::Reader aReader(
134 aBytes.getConstArray(), aBytes.getLength(), false,
135 TYPEREG_VERSION_1);
136
137 rtl::OUString aName(
138 aReader.getTypeName().replace( '/', '.' ) );
139
140 if ( aReader.getTypeClass() == RT_TYPE_MODULE )
141 {
142 // Do not close xKey!
143 aCloser.reset();
144
145 aModuleKeys.push_back( xKey );
146 }
147 }
148 }
149 else
150 {
151 OSL_ENSURE(
152 sal_False,
153 "TypeDescriptionEnumerationImpl::createInstance "
154 "- Invalid registry key!" );
155 }
156 }
157 }
158 catch ( registry::InvalidRegistryException const & )
159 {
160 // openKey, getValueType, getBinaryValue
161
162 OSL_ENSURE( sal_False,
163 "TypeDescriptionEnumerationImpl::createInstance "
164 "- Caught InvalidRegistryException!" );
165 }
166
167 it++;
168 }
169
170 if ( !bOpenKeySucceeded )
171 throw reflection::NoSuchTypeNameException();
172
173 if ( aModuleKeys.size() == 0 )
174 throw reflection::InvalidTypeNameException();
175
176 return rtl::Reference< TypeDescriptionEnumerationImpl >(
177 new TypeDescriptionEnumerationImpl(
178 xTDMgr, aModuleKeys, rTypes, eDepth ) );
179 }
180
181 //=========================================================================
TypeDescriptionEnumerationImpl(const uno::Reference<container::XHierarchicalNameAccess> & xTDMgr,const RegistryKeyList & rModuleKeys,const uno::Sequence<uno::TypeClass> & rTypes,reflection::TypeDescriptionSearchDepth eDepth)182 TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl(
183 const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
184 const RegistryKeyList & rModuleKeys,
185 const uno::Sequence< uno::TypeClass > & rTypes,
186 reflection::TypeDescriptionSearchDepth eDepth )
187 : m_aModuleKeys( rModuleKeys ),
188 m_aTypes( rTypes ),
189 m_eDepth( eDepth ),
190 m_xTDMgr( xTDMgr )
191 {
192 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
193 }
194
195 //=========================================================================
196 // virtual
~TypeDescriptionEnumerationImpl()197 TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl()
198 {
199 RegistryKeyList::const_iterator it = m_aModuleKeys.begin();
200 RegistryKeyList::const_iterator end = m_aModuleKeys.end();
201 /*
202 @@@ in case we enumerate root and queryMore was never called, then
203 m_aModuleKeys contains open root keys which where passed from
204 tdprov and must not be closed by us.
205
206 while ( it != end )
207 {
208 try
209 {
210 if ( (*it)->isValid() )
211 (*it)->closeKey();
212 }
213 catch (...)
214 {
215 // No exceptions from dtors, please!
216 OSL_ENSURE( sal_False,
217 "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
218 "- Caught exception!" );
219 }
220
221 it++;
222 }
223 */
224 it = m_aCurrentModuleSubKeys.begin();
225 end = m_aCurrentModuleSubKeys.end();
226 while ( it != end )
227 {
228 try
229 {
230 if ( (*it)->isValid() )
231 (*it)->closeKey();
232 }
233 catch (Exception &)
234 {
235 // No exceptions from dtors, please!
236 OSL_ENSURE( sal_False,
237 "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
238 "- Caught exception!" );
239 }
240
241 it++;
242 }
243
244 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
245 }
246
247 //=========================================================================
248 //
249 // XEnumeration (base of XTypeDescriptionEnumeration) methods
250 //
251 //=========================================================================
252
253 // virtual
hasMoreElements()254 sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements()
255 throw ( uno::RuntimeException )
256 {
257 return queryMore();
258 }
259
260 //=========================================================================
261 // virtual
nextElement()262 uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement()
263 throw ( container::NoSuchElementException,
264 lang::WrappedTargetException,
265 uno::RuntimeException )
266 {
267 return uno::Any( uno::makeAny( nextTypeDescription() ) );
268 }
269
270 //=========================================================================
271 //
272 // XTypeDescriptionEnumeration methods
273 //
274 //=========================================================================
275
276 // virtual
277 uno::Reference< reflection::XTypeDescription > SAL_CALL
nextTypeDescription()278 TypeDescriptionEnumerationImpl::nextTypeDescription()
279 throw ( container::NoSuchElementException,
280 uno::RuntimeException )
281 {
282 uno::Reference< reflection::XTypeDescription > xTD( queryNext() );
283
284 if ( xTD.is() )
285 return xTD;
286
287 throw container::NoSuchElementException(
288 rtl::OUString::createFromAscii(
289 "No further elements in enumeration!" ),
290 static_cast< cppu::OWeakObject * >( this ) );
291 }
292
293 //=========================================================================
match(RTTypeClass eType1,uno::TypeClass eType2)294 bool TypeDescriptionEnumerationImpl::match(
295 RTTypeClass eType1, uno::TypeClass eType2 )
296 {
297 switch ( eType1 )
298 {
299 case RT_TYPE_INTERFACE:
300 return eType2 == uno::TypeClass_INTERFACE;
301
302 case RT_TYPE_MODULE:
303 return eType2 == uno::TypeClass_MODULE;
304
305 case RT_TYPE_STRUCT:
306 return eType2 == uno::TypeClass_STRUCT;
307
308 case RT_TYPE_ENUM:
309 return eType2 == uno::TypeClass_ENUM;
310
311 case RT_TYPE_EXCEPTION:
312 return eType2 == uno::TypeClass_EXCEPTION;
313
314 case RT_TYPE_TYPEDEF:
315 return eType2 == uno::TypeClass_TYPEDEF;
316
317 case RT_TYPE_SERVICE:
318 return eType2 == uno::TypeClass_SERVICE;
319
320 case RT_TYPE_SINGLETON:
321 return eType2 == uno::TypeClass_SINGLETON;
322
323 case RT_TYPE_CONSTANTS:
324 return eType2 == uno::TypeClass_CONSTANTS;
325
326 case RT_TYPE_UNION:
327 return eType2 == uno::TypeClass_UNION;
328
329 default:
330 return false;
331 }
332 }
333
334 //=========================================================================
queryMore()335 bool TypeDescriptionEnumerationImpl::queryMore()
336 {
337 osl::MutexGuard aGuard( m_aMutex );
338
339 for (;;)
340 {
341 if ( !m_aCurrentModuleSubKeys.empty() || !m_aTypeDescs.empty() )
342 {
343 // Okay, there is at least one more element.
344 return true;
345 }
346
347 if ( m_aModuleKeys.empty() )
348 {
349 // No module keys (therefore no elements) left.
350 return false;
351 }
352
353 // Note: m_aCurrentModuleSubKeys is always empty AND m_aModuleKeys is
354 // never empty when ariving here.
355 // ==> select new module key, fill m_aCurrentModuleSubKeys
356
357 uno::Sequence< uno::Reference< registry::XRegistryKey > > aKeys;
358 try
359 {
360 aKeys = m_aModuleKeys.front()->openKeys();
361 for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
362 {
363 uno::Reference< registry::XRegistryKey > xKey = aKeys[ n ];
364
365 // closes key in it's dtor (which is
366 // called even in case of exceptions).
367 RegistryKeyCloser aCloser( xKey );
368
369 try
370 {
371 if ( xKey->isValid() )
372 {
373 if ( xKey->getValueType()
374 == registry::RegistryValueType_BINARY )
375 {
376 bool bIncludeIt = (m_aTypes.getLength() == 0);
377 bool bNeedTypeClass =
378 ((m_aTypes.getLength() > 0) ||
379 (m_eDepth
380 == reflection::TypeDescriptionSearchDepth_INFINITE));
381 if ( bNeedTypeClass )
382 {
383 uno::Sequence< sal_Int8 > aBytes(
384 xKey->getBinaryValue() );
385
386 typereg::Reader aReader(
387 aBytes.getConstArray(), aBytes.getLength(),
388 false, TYPEREG_VERSION_1);
389
390 RTTypeClass eTypeClass = aReader.getTypeClass();
391
392 // Does key match requested types? Empty
393 // sequence means include all.
394 if ( m_aTypes.getLength() > 0 )
395 {
396 for ( sal_Int32 m = 0;
397 m < m_aTypes.getLength();
398 ++m )
399 {
400 if ( match(eTypeClass, m_aTypes[ m ]) )
401 {
402 bIncludeIt = true;
403 break;
404 }
405 }
406 }
407
408 if ( m_eDepth ==
409 reflection::TypeDescriptionSearchDepth_INFINITE )
410 {
411 if ( eTypeClass == RT_TYPE_MODULE )
412 {
413 // Do not close xKey!
414 aCloser.reset();
415
416 // Remember new module key.
417 m_aModuleKeys.push_back( xKey );
418 }
419 }
420 }
421
422 if ( bIncludeIt )
423 {
424 // Do not close xKey!
425 aCloser.reset();
426
427 m_aCurrentModuleSubKeys.push_back( xKey );
428 }
429 }
430 }
431 else
432 {
433 OSL_ENSURE( sal_False,
434 "TypeDescriptionEnumerationImpl::queryMore "
435 "- Invalid registry key!" );
436 }
437
438 }
439 catch ( registry::InvalidRegistryException const & )
440 {
441 // getValueType, getBinaryValue
442
443 OSL_ENSURE( sal_False,
444 "TypeDescriptionEnumerationImpl::queryMore "
445 "- Caught InvalidRegistryException!" );
446
447 // Don't stop iterating!
448 }
449 }
450 }
451 catch ( registry::InvalidRegistryException const & )
452 {
453 // openKeys
454
455 for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
456 {
457 try
458 {
459 aKeys[ n ]->closeKey();
460 }
461 catch ( registry::InvalidRegistryException const & )
462 {
463 OSL_ENSURE( sal_False,
464 "TypeDescriptionEnumerationImpl::queryMore "
465 "- Caught InvalidRegistryException!" );
466 }
467 }
468 }
469
470 /////////////////////////////////////////////////////////////////////
471 // Special handling for constants contained directly in module.
472 /////////////////////////////////////////////////////////////////////
473
474 // Constants requested?
475 bool bIncludeConstants = ( m_aTypes.getLength() == 0 );
476 if ( !bIncludeConstants )
477 {
478 for ( sal_Int32 m = 0; m < m_aTypes.getLength(); ++m )
479 {
480 if ( m_aTypes[ m ] == uno::TypeClass_CONSTANT )
481 {
482 bIncludeConstants = true;
483 break;
484 }
485 }
486
487 }
488
489 if ( bIncludeConstants )
490 {
491 if ( m_aModuleKeys.front()->getValueType()
492 == registry::RegistryValueType_BINARY )
493 {
494 try
495 {
496 uno::Sequence< sal_Int8 > aBytes(
497 m_aModuleKeys.front()->getBinaryValue() );
498
499 typereg::Reader aReader(
500 aBytes.getConstArray(), aBytes.getLength(), false,
501 TYPEREG_VERSION_1);
502
503 if ( aReader.getTypeClass() == RT_TYPE_MODULE )
504 {
505 sal_uInt16 nFields = aReader.getFieldCount();
506 while ( nFields-- )
507 {
508 rtl::OUStringBuffer aName(
509 aReader.getTypeName().replace( '/', '.' ) );
510 aName.appendAscii( "." );
511 aName.append( aReader.getFieldName( nFields ) );
512
513 uno::Any aValue(
514 getRTValue(
515 aReader.getFieldValue( nFields ) ) );
516
517 m_aTypeDescs.push_back(
518 new IndividualConstantTypeDescriptionImpl(
519 aName.makeStringAndClear(), aValue,
520 ( ( aReader.getFieldFlags( nFields )
521 & RT_ACCESS_PUBLISHED )
522 != 0 ) ) );
523 }
524 }
525 }
526 catch ( registry::InvalidRegistryException const & )
527 {
528 // getBinaryValue
529
530 OSL_ENSURE( sal_False,
531 "TypeDescriptionEnumerationImpl::queryMore "
532 "- Caught InvalidRegistryException!" );
533 }
534 }
535 }
536
537 /////////////////////////////////////////////////////////////////////
538
539 /*
540 @@@ m_aModuleKeys.front() may have open sub keys (may be contained in
541 both m_aModuleKeys and m_aCurrentModuleSubKeys)!
542
543 try
544 {
545 m_aModuleKeys.front()->closeKey();
546 }
547 catch ( registry::InvalidRegistryException const & )
548 {
549 OSL_ENSURE( sal_False,
550 "TypeDescriptionEnumerationImpl::queryMore "
551 "- Caught InvalidRegistryException!" );
552 }
553 */
554 // We're done with this module key, even if there were errors.
555 m_aModuleKeys.pop_front();
556 }
557
558 // unreachable
559 }
560
561 //=========================================================================
562 uno::Reference< reflection::XTypeDescription >
queryNext()563 TypeDescriptionEnumerationImpl::queryNext()
564 {
565 osl::MutexGuard aGuard( m_aMutex );
566
567 for (;;)
568 {
569 if ( !queryMore() )
570 return uno::Reference< reflection::XTypeDescription >();
571
572 uno::Reference< reflection::XTypeDescription > xTD;
573
574 if ( !m_aTypeDescs.empty() )
575 {
576 xTD = m_aTypeDescs.front();
577 m_aTypeDescs.pop_front();
578 return xTD;
579 }
580
581 // Note: xKey is already opened.
582 uno::Reference< registry::XRegistryKey >
583 xKey( m_aCurrentModuleSubKeys.front() );
584 /*
585 @@@ xKey may still be contained in m_aModuleKeys, too
586
587 // closes key in it's dtor (which is
588 // called even in case of exceptions).
589 RegistryKeyCloser aCloser( xKey );
590 */
591 try
592 {
593 {
594 if ( xKey->isValid() )
595 {
596 if ( xKey->getValueType()
597 == registry::RegistryValueType_BINARY )
598 {
599 uno::Sequence< sal_Int8 > aBytes(
600 xKey->getBinaryValue() );
601
602 xTD = createTypeDescription( aBytes,
603 m_xTDMgr,
604 false );
605 OSL_ENSURE( xTD.is(),
606 "TypeDescriptionEnumerationImpl::queryNext "
607 "- No XTypeDescription created!" );
608 }
609 }
610 else
611 {
612 OSL_ENSURE( sal_False,
613 "TypeDescriptionEnumerationImpl::queryNext "
614 "- Invalid registry key!" );
615 }
616 }
617 }
618 catch ( registry::InvalidRegistryException const & )
619 {
620 // getValueType, getBinaryValue
621
622 OSL_ENSURE( sal_False,
623 "TypeDescriptionEnumerationImpl::queryNext "
624 "- Caught InvalidRegistryException!" );
625 }
626
627 // We're done with this key, even if there were errors.
628 m_aCurrentModuleSubKeys.pop_front();
629
630 if ( xTD.is() )
631 return xTD;
632
633 // next try...
634
635 } // for (;;)
636 }
637
638 } // namespace stoc_rdbtdp
639
640