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_embeddedobj.hxx" 26 #include <com/sun/star/embed/ElementModes.hpp> 27 #include <com/sun/star/embed/EntryInitModes.hpp> 28 #include <com/sun/star/document/XTypeDetection.hpp> 29 #include <com/sun/star/beans/PropertyValue.hpp> 30 #include <com/sun/star/beans/XPropertySet.hpp> 31 #include <com/sun/star/container/XNameAccess.hpp> 32 33 #include <rtl/logfile.hxx> 34 35 36 #include "xfactory.hxx" 37 #include "commonembobj.hxx" 38 #include "specialobject.hxx" 39 #include "oleembobj.hxx" 40 41 42 using namespace ::com::sun::star; 43 44 //------------------------------------------------------------------------- 45 uno::Sequence< ::rtl::OUString > SAL_CALL OOoEmbeddedObjectFactory::impl_staticGetSupportedServiceNames() 46 { 47 uno::Sequence< ::rtl::OUString > aRet(2); 48 aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoEmbeddedObjectFactory"); 49 aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoEmbeddedObjectFactory"); 50 return aRet; 51 } 52 53 //------------------------------------------------------------------------- 54 ::rtl::OUString SAL_CALL OOoEmbeddedObjectFactory::impl_staticGetImplementationName() 55 { 56 return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoEmbeddedObjectFactory"); 57 } 58 59 //------------------------------------------------------------------------- 60 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::impl_staticCreateSelfInstance( 61 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) 62 { 63 return uno::Reference< uno::XInterface >( *new OOoEmbeddedObjectFactory( xServiceManager ) ); 64 } 65 66 //------------------------------------------------------------------------- 67 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitFromEntry( 68 const uno::Reference< embed::XStorage >& xStorage, 69 const ::rtl::OUString& sEntName, 70 const uno::Sequence< beans::PropertyValue >& aMediaDescr, 71 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 72 { 73 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitFromEntry" ); 74 75 if ( !xStorage.is() ) 76 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 77 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 78 1 ); 79 80 if ( !sEntName.getLength() ) 81 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 82 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 83 2 ); 84 85 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); 86 if ( !xNameAccess.is() ) 87 throw uno::RuntimeException(); //TODO 88 89 // detect entry existence 90 if ( !xNameAccess->hasByName( sEntName ) ) 91 throw container::NoSuchElementException(); 92 93 uno::Reference< uno::XInterface > xResult; 94 if ( xStorage->isStorageElement( sEntName ) ) 95 { 96 // the object must be based on storage 97 uno::Reference< embed::XStorage > xSubStorage = 98 xStorage->openStorageElement( sEntName, embed::ElementModes::READ ); 99 100 uno::Reference< beans::XPropertySet > xPropSet( xSubStorage, uno::UNO_QUERY ); 101 if ( !xPropSet.is() ) 102 throw uno::RuntimeException(); 103 104 ::rtl::OUString aMediaType; 105 try { 106 uno::Any aAny = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ); 107 aAny >>= aMediaType; 108 } 109 catch ( uno::Exception& ) 110 { 111 } 112 113 try { 114 uno::Reference< lang::XComponent > xComp( xSubStorage, uno::UNO_QUERY ); 115 if ( xComp.is() ) 116 xComp->dispose(); 117 } 118 catch ( uno::Exception& ) 119 { 120 } 121 xSubStorage = uno::Reference< embed::XStorage >(); 122 123 #if 0 124 ::rtl::OUString aDocServiceName = m_aConfigHelper.GetDocumentServiceFromMediaType( aMediaType ); 125 if ( !aDocServiceName.getLength() ) 126 { 127 // only own document can be based on storage 128 // in case it is not possible to find related 129 // document service name the storage entry is invalid 130 131 throw io::IOException(); // unexpected mimetype of the storage 132 } 133 #endif 134 135 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByMediaType( aMediaType ); 136 if ( !aObject.getLength() ) 137 throw io::IOException(); // unexpected mimetype of the storage 138 139 xResult = uno::Reference< uno::XInterface >( 140 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 141 m_xFactory, 142 aObject ) ), 143 #if 0 144 GetClassIDFromServName( aDocServiceName ), 145 GetClassNameFromServName( aDocServiceName ), 146 aDocServiceName ) ), 147 #endif 148 uno::UNO_QUERY ); 149 } 150 else 151 { 152 // the object must be OOo embedded object, if it is not an exception must be thrown 153 throw io::IOException(); // TODO: 154 } 155 156 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); 157 158 if ( !xPersist.is() ) 159 throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects 160 161 xPersist->setPersistentEntry( xStorage, 162 sEntName, 163 embed::EntryInitModes::DEFAULT_INIT, 164 aMediaDescr, 165 lObjArgs ); 166 167 return xResult; 168 } 169 170 //------------------------------------------------------------------------- 171 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor( 172 const uno::Reference< embed::XStorage >& xStorage, 173 const ::rtl::OUString& sEntName, 174 const uno::Sequence< beans::PropertyValue >& aMediaDescr, 175 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 176 { 177 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor" ); 178 179 if ( !xStorage.is() ) 180 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 181 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 182 1 ); 183 184 if ( !sEntName.getLength() ) 185 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 186 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 187 2 ); 188 189 uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr ); 190 191 // check if there is FilterName 192 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False ); 193 194 uno::Reference< uno::XInterface > xResult; 195 196 // find document service name 197 if ( aFilterName.getLength() ) 198 { 199 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByFilter( aFilterName ); 200 if ( !aObject.getLength() ) 201 throw io::IOException(); // unexpected mimetype of the storage 202 203 204 xResult = uno::Reference< uno::XInterface >( 205 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 206 m_xFactory, 207 aObject ) ), 208 uno::UNO_QUERY ); 209 } 210 else 211 { 212 // the object must be OOo embedded object, if it is not an exception must be thrown 213 throw io::IOException(); // TODO: 214 } 215 216 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); 217 218 if ( !xPersist.is() ) 219 throw uno::RuntimeException(); // TODO: the interface must be supported ( what about applets? ) 220 221 xPersist->setPersistentEntry( xStorage, 222 sEntName, 223 embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT, 224 aTempMedDescr, 225 lObjArgs ); 226 227 return xResult; 228 } 229 230 //------------------------------------------------------------------------- 231 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceInitNew( 232 const uno::Sequence< sal_Int8 >& aClassID, 233 const ::rtl::OUString& /*aClassName*/, 234 const uno::Reference< embed::XStorage >& xStorage, 235 const ::rtl::OUString& sEntName, 236 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 237 { 238 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceInitNew" ); 239 240 uno::Reference< uno::XInterface > xResult; 241 242 if ( !xStorage.is() ) 243 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 244 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 245 3 ); 246 247 if ( !sEntName.getLength() ) 248 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 249 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 250 4 ); 251 252 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID ); 253 if ( !aObject.getLength() ) 254 throw io::IOException(); // unexpected mimetype of the storage 255 256 xResult = uno::Reference< uno::XInterface >( 257 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 258 m_xFactory, 259 aObject ) ), 260 uno::UNO_QUERY ); 261 262 263 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); 264 265 if ( !xPersist.is() ) 266 throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects 267 268 xPersist->setPersistentEntry( xStorage, 269 sEntName, 270 embed::EntryInitModes::TRUNCATE_INIT, 271 uno::Sequence< beans::PropertyValue >(), 272 lObjArgs ); 273 274 return xResult; 275 } 276 277 //------------------------------------------------------------------------- 278 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceUserInit( 279 const uno::Sequence< sal_Int8 >& aClassID, 280 const ::rtl::OUString& /*aClassName*/, 281 const uno::Reference< embed::XStorage >& xStorage, 282 const ::rtl::OUString& sEntName, 283 sal_Int32 nEntryConnectionMode, 284 const uno::Sequence< beans::PropertyValue >& lArguments, 285 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 286 { 287 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceUserInit" ); 288 289 // the initialization is completely controlled by user 290 if ( !xStorage.is() ) 291 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 292 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 293 1 ); 294 295 if ( !sEntName.getLength() ) 296 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 297 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 298 2 ); 299 300 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID ); 301 if ( !aObject.getLength() ) 302 throw io::IOException(); // unexpected mimetype of the storage 303 304 uno::Sequence< beans::PropertyValue > aTempMedDescr( lArguments ); 305 if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ) 306 { 307 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, aObject ); 308 if ( !aFilterName.getLength() ) 309 // the object must be OOo embedded object, if it is not an exception must be thrown 310 throw io::IOException(); // TODO: 311 } 312 313 uno::Reference< uno::XInterface > xResult = uno::Reference< uno::XInterface > ( 314 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 315 m_xFactory, 316 aObject ) ), 317 uno::UNO_QUERY ); 318 319 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); 320 if ( xPersist.is() ) 321 { 322 xPersist->setPersistentEntry( xStorage, 323 sEntName, 324 nEntryConnectionMode, 325 aTempMedDescr, 326 lObjArgs ); 327 328 } 329 else 330 throw uno::RuntimeException(); // TODO: 331 332 return xResult; 333 } 334 335 336 //------------------------------------------------------------------------- 337 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceLink( 338 const uno::Reference< embed::XStorage >& /*xStorage*/, 339 const ::rtl::OUString& /*sEntName*/, 340 const uno::Sequence< beans::PropertyValue >& aMediaDescr, 341 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 342 { 343 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceLink" ); 344 345 uno::Reference< uno::XInterface > xResult; 346 347 uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr ); 348 349 // check if there is URL, URL must exist 350 ::rtl::OUString aURL; 351 for ( sal_Int32 nInd = 0; nInd < aTempMedDescr.getLength(); nInd++ ) 352 if ( aTempMedDescr[nInd].Name.equalsAscii( "URL" ) ) 353 aTempMedDescr[nInd].Value >>= aURL; 354 355 if ( !aURL.getLength() ) 356 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No URL for the link is provided!\n" ), 357 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 358 3 ); 359 360 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False ); 361 362 if ( aFilterName.getLength() ) 363 { 364 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByFilter( aFilterName ); 365 if ( !aObject.getLength() ) 366 throw io::IOException(); // unexpected mimetype of the storage 367 368 369 xResult = uno::Reference< uno::XInterface >( 370 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 371 m_xFactory, 372 aObject, 373 aTempMedDescr, 374 lObjArgs ) ), 375 uno::UNO_QUERY ); 376 } 377 else 378 { 379 // the object must be OOo embedded object, if it is not an exception must be thrown 380 throw io::IOException(); // TODO: 381 } 382 383 return xResult; 384 } 385 386 //------------------------------------------------------------------------- 387 uno::Reference< uno::XInterface > SAL_CALL OOoEmbeddedObjectFactory::createInstanceLinkUserInit( 388 const uno::Sequence< sal_Int8 >& aClassID, 389 const ::rtl::OUString& /*aClassName*/, 390 const uno::Reference< embed::XStorage >& xStorage, 391 const ::rtl::OUString& sEntName, 392 const uno::Sequence< beans::PropertyValue >& lArguments, 393 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 394 { 395 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OOoEmbeddedObjectFactory::createInstanceLinkUserInit" ); 396 397 uno::Reference< uno::XInterface > xResult; 398 399 // the initialization is completely controlled by user 400 if ( !xStorage.is() ) 401 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 402 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 403 1 ); 404 405 if ( !sEntName.getLength() ) 406 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 407 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 408 2 ); 409 410 uno::Sequence< beans::PropertyValue > aTempMedDescr( lArguments ); 411 412 ::rtl::OUString aURL; 413 for ( sal_Int32 nInd = 0; nInd < aTempMedDescr.getLength(); nInd++ ) 414 if ( aTempMedDescr[nInd].Name.equalsAscii( "URL" ) ) 415 aTempMedDescr[nInd].Value >>= aURL; 416 417 if ( !aURL.getLength() ) 418 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No URL for the link is provided!\n" ), 419 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 420 3 ); 421 422 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID ); 423 if ( !aObject.getLength() ) 424 throw io::IOException(); // unexpected mimetype of the storage 425 426 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, aObject ); 427 428 if ( aFilterName.getLength() ) 429 { 430 431 xResult = uno::Reference< uno::XInterface >( 432 static_cast< ::cppu::OWeakObject* > ( new OCommonEmbeddedObject( 433 m_xFactory, 434 aObject, 435 aTempMedDescr, 436 lObjArgs ) ), 437 uno::UNO_QUERY ); 438 } 439 else 440 { 441 // the object must be OOo embedded object, if it is not an exception must be thrown 442 throw io::IOException(); // TODO: 443 } 444 445 return xResult; 446 } 447 448 //------------------------------------------------------------------------- 449 ::rtl::OUString SAL_CALL OOoEmbeddedObjectFactory::getImplementationName() 450 { 451 return impl_staticGetImplementationName(); 452 } 453 454 //------------------------------------------------------------------------- 455 sal_Bool SAL_CALL OOoEmbeddedObjectFactory::supportsService( const ::rtl::OUString& ServiceName ) 456 { 457 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); 458 459 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 460 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) 461 return sal_True; 462 463 return sal_False; 464 } 465 466 //------------------------------------------------------------------------- 467 uno::Sequence< ::rtl::OUString > SAL_CALL OOoEmbeddedObjectFactory::getSupportedServiceNames() 468 { 469 return impl_staticGetSupportedServiceNames(); 470 } 471 472 //------------------------------------------------------------------------- 473 uno::Sequence< ::rtl::OUString > SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticGetSupportedServiceNames() 474 { 475 uno::Sequence< ::rtl::OUString > aRet(2); 476 aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"); 477 aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoSpecialEmbeddedObjectFactory"); 478 return aRet; 479 } 480 481 //------------------------------------------------------------------------- 482 ::rtl::OUString SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticGetImplementationName() 483 { 484 return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OOoSpecialEmbeddedObjectFactory"); 485 } 486 487 //------------------------------------------------------------------------- 488 uno::Reference< uno::XInterface > SAL_CALL OOoSpecialEmbeddedObjectFactory::impl_staticCreateSelfInstance( 489 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) 490 { 491 return uno::Reference< uno::XInterface >( *new OOoSpecialEmbeddedObjectFactory( xServiceManager ) ); 492 } 493 494 //------------------------------------------------------------------------- 495 uno::Reference< uno::XInterface > SAL_CALL OOoSpecialEmbeddedObjectFactory::createInstanceUserInit( 496 const uno::Sequence< sal_Int8 >& aClassID, 497 const ::rtl::OUString& /*aClassName*/, 498 const uno::Reference< embed::XStorage >& /*xStorage*/, 499 const ::rtl::OUString& /*sEntName*/, 500 sal_Int32 /*nEntryConnectionMode*/, 501 const uno::Sequence< beans::PropertyValue >& /*lArguments*/, 502 const uno::Sequence< beans::PropertyValue >& /*lObjArgs*/ ) 503 { 504 uno::Sequence< beans::NamedValue > aObject = m_aConfigHelper.GetObjectPropsByClassID( aClassID ); 505 if ( !aObject.getLength() ) 506 throw io::IOException(); // unexpected mimetype of the storage 507 508 uno::Reference< uno::XInterface > xResult( 509 static_cast< ::cppu::OWeakObject* > ( new OSpecialEmbeddedObject( 510 m_xFactory, 511 aObject ) ), 512 uno::UNO_QUERY ); 513 return xResult; 514 } 515 516 //------------------------------------------------------------------------- 517 ::rtl::OUString SAL_CALL OOoSpecialEmbeddedObjectFactory::getImplementationName() 518 { 519 return impl_staticGetImplementationName(); 520 } 521 522 //------------------------------------------------------------------------- 523 sal_Bool SAL_CALL OOoSpecialEmbeddedObjectFactory::supportsService( const ::rtl::OUString& ServiceName ) 524 { 525 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); 526 527 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 528 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) 529 return sal_True; 530 531 return sal_False; 532 } 533 534 //------------------------------------------------------------------------- 535 uno::Sequence< ::rtl::OUString > SAL_CALL OOoSpecialEmbeddedObjectFactory::getSupportedServiceNames() 536 { 537 return impl_staticGetSupportedServiceNames(); 538 } 539