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