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