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: 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 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 > 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 //========================================================================= 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 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 254 sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements() 255 throw ( uno::RuntimeException ) 256 { 257 return queryMore(); 258 } 259 260 //========================================================================= 261 // virtual 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 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 //========================================================================= 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 //========================================================================= 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 > 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