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_embeddedobj.hxx" 30 #include <com/sun/star/embed/ElementModes.hpp> 31 #include <com/sun/star/embed/EntryInitModes.hpp> 32 #include <com/sun/star/embed/XEmbedObjectFactory.hpp> 33 #include <com/sun/star/embed/XLinkFactory.hpp> 34 #include <com/sun/star/document/XTypeDetection.hpp> 35 #include <com/sun/star/beans/PropertyValue.hpp> 36 #include <com/sun/star/beans/XPropertySet.hpp> 37 #include <com/sun/star/container/XNameAccess.hpp> 38 #include <com/sun/star/lang/XComponent.hpp> 39 40 #include <rtl/logfile.hxx> 41 42 43 #include <xcreator.hxx> 44 #include <dummyobject.hxx> 45 46 47 using namespace ::com::sun::star; 48 49 50 //------------------------------------------------------------------------- 51 uno::Sequence< ::rtl::OUString > SAL_CALL UNOEmbeddedObjectCreator::impl_staticGetSupportedServiceNames() 52 { 53 uno::Sequence< ::rtl::OUString > aRet(2); 54 aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.EmbeddedObjectCreator"); 55 aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.EmbeddedObjectCreator"); 56 return aRet; 57 } 58 59 //------------------------------------------------------------------------- 60 ::rtl::OUString SAL_CALL UNOEmbeddedObjectCreator::impl_staticGetImplementationName() 61 { 62 return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.EmbeddedObjectCreator"); 63 } 64 65 //------------------------------------------------------------------------- 66 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::impl_staticCreateSelfInstance( 67 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) 68 { 69 return uno::Reference< uno::XInterface >( *new UNOEmbeddedObjectCreator( xServiceManager ) ); 70 } 71 72 //------------------------------------------------------------------------- 73 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitNew( 74 const uno::Sequence< sal_Int8 >& aClassID, 75 const ::rtl::OUString& aClassName, 76 const uno::Reference< embed::XStorage >& xStorage, 77 const ::rtl::OUString& sEntName, 78 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 79 throw ( lang::IllegalArgumentException, 80 io::IOException, 81 uno::Exception, 82 uno::RuntimeException) 83 { 84 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceInitNew" ); 85 86 uno::Reference< uno::XInterface > xResult; 87 88 if ( !xStorage.is() ) 89 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 90 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 91 3 ); 92 93 if ( !sEntName.getLength() ) 94 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 95 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 96 4 ); 97 98 ::rtl::OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID ); 99 if ( !aEmbedFactory.getLength() ) 100 { 101 // use system fallback 102 // TODO: in future users factories can be tested 103 aEmbedFactory = ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLEEmbeddedObjectFactory" ); 104 } 105 106 uno::Reference < uno::XInterface > xFact( m_xFactory->createInstance( aEmbedFactory ) ); 107 uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY ); 108 if ( xEmbCreator.is() ) 109 return xEmbCreator->createInstanceInitNew( aClassID, aClassName, xStorage, sEntName, lObjArgs ); 110 111 uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY ); 112 if ( !xEmbFact.is() ) 113 throw uno::RuntimeException(); 114 return xEmbFact->createInstanceUserInit( aClassID, aClassName, xStorage, sEntName, embed::EntryInitModes::TRUNCATE_INIT, uno::Sequence < beans::PropertyValue >(), lObjArgs); 115 } 116 117 //------------------------------------------------------------------------- 118 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromEntry( 119 const uno::Reference< embed::XStorage >& xStorage, 120 const ::rtl::OUString& sEntName, 121 const uno::Sequence< beans::PropertyValue >& aMedDescr, 122 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 123 throw ( lang::IllegalArgumentException, 124 container::NoSuchElementException, 125 io::IOException, 126 uno::Exception, 127 uno::RuntimeException) 128 { 129 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceInitFromEntry" ); 130 131 if ( !xStorage.is() ) 132 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 133 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 134 1 ); 135 136 if ( !sEntName.getLength() ) 137 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 138 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 139 2 ); 140 141 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); 142 if ( !xNameAccess.is() ) 143 throw uno::RuntimeException(); //TODO 144 145 // detect entry existence 146 if ( !xNameAccess->hasByName( sEntName ) ) 147 throw container::NoSuchElementException(); 148 149 ::rtl::OUString aMediaType; 150 ::rtl::OUString aEmbedFactory; 151 if ( xStorage->isStorageElement( sEntName ) ) 152 { 153 // the object must be based on storage 154 uno::Reference< embed::XStorage > xSubStorage = 155 xStorage->openStorageElement( sEntName, embed::ElementModes::READ ); 156 157 uno::Reference< beans::XPropertySet > xPropSet( xSubStorage, uno::UNO_QUERY ); 158 if ( !xPropSet.is() ) 159 throw uno::RuntimeException(); 160 161 try { 162 uno::Any aAny = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ); 163 aAny >>= aMediaType; 164 } 165 catch ( uno::Exception& ) 166 { 167 } 168 169 try { 170 uno::Reference< lang::XComponent > xComp( xSubStorage, uno::UNO_QUERY ); 171 if ( xComp.is() ) 172 xComp->dispose(); 173 } 174 catch ( uno::Exception& ) 175 { 176 } 177 } 178 else 179 { 180 // the object must be based on stream 181 // it means for now that this is an OLE object 182 183 // the object will be created as embedded object 184 // after it is loaded it can detect that it is a link 185 186 uno::Reference< io::XStream > xSubStream = 187 xStorage->openStreamElement( sEntName, embed::ElementModes::READ ); 188 189 uno::Reference< beans::XPropertySet > xPropSet( xSubStream, uno::UNO_QUERY ); 190 if ( !xPropSet.is() ) 191 throw uno::RuntimeException(); 192 193 try { 194 uno::Any aAny = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ); 195 aAny >>= aMediaType; 196 if ( aMediaType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) ) 197 aEmbedFactory = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLEEmbeddedObjectFactory" ) ); 198 } 199 catch ( uno::Exception& ) 200 { 201 } 202 203 try { 204 uno::Reference< lang::XComponent > xComp( xSubStream, uno::UNO_QUERY ); 205 if ( xComp.is() ) 206 xComp->dispose(); 207 } 208 catch ( uno::Exception& ) 209 { 210 } 211 } 212 213 OSL_ENSURE( aMediaType.getLength(), "No media type is specified for the object!" ); 214 if ( aMediaType.getLength() && !aEmbedFactory.getLength() ) 215 aEmbedFactory = m_aConfigHelper.GetFactoryNameByMediaType( aMediaType ); 216 217 if ( aEmbedFactory.getLength() ) 218 { 219 uno::Reference< uno::XInterface > xFact = m_xFactory->createInstance( aEmbedFactory ); 220 221 uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY ); 222 if ( xEmbCreator.is() ) 223 return xEmbCreator->createInstanceInitFromEntry( xStorage, sEntName, aMedDescr, lObjArgs ); 224 225 uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY ); 226 if ( xEmbFact.is() ) 227 return xEmbFact->createInstanceUserInit( uno::Sequence< sal_Int8 >(), ::rtl::OUString(), xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs); 228 } 229 230 // the default object should be created, it will allow to store the contents on the next saving 231 uno::Reference< uno::XInterface > xResult( static_cast< cppu::OWeakObject* >( new ODummyEmbeddedObject() ) ); 232 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY_THROW ); 233 xPersist->setPersistentEntry( xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs ); 234 return xResult; 235 } 236 237 //------------------------------------------------------------------------- 238 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromMediaDescriptor( 239 const uno::Reference< embed::XStorage >& xStorage, 240 const ::rtl::OUString& sEntName, 241 const uno::Sequence< beans::PropertyValue >& aMediaDescr, 242 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 243 throw ( lang::IllegalArgumentException, 244 io::IOException, 245 uno::Exception, 246 uno::RuntimeException) 247 { 248 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceInitFromMediaDescriptor" ); 249 250 // TODO: use lObjArgs 251 252 if ( !xStorage.is() ) 253 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 254 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 255 1 ); 256 257 if ( !sEntName.getLength() ) 258 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 259 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 260 2 ); 261 262 uno::Reference< uno::XInterface > xResult; 263 uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr ); 264 265 // check if there is FilterName 266 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False ); 267 268 if ( aFilterName.getLength() ) 269 { 270 // the object can be loaded by one of the office application 271 uno::Reference< embed::XEmbedObjectCreator > xOOoEmbCreator( 272 m_xFactory->createInstance( 273 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OOoEmbeddedObjectFactory" ) ), 274 uno::UNO_QUERY ); 275 if ( !xOOoEmbCreator.is() ) 276 throw uno::RuntimeException(); // TODO: 277 278 xResult = xOOoEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, 279 sEntName, 280 aTempMedDescr, 281 lObjArgs ); 282 } 283 else 284 { 285 // must be an OLE object 286 287 // TODO: in future, when more object types are possible this place seems 288 // to be a weak one, probably configuration must provide a type detection service 289 // for every factory, so any file could go through services until it is recognized 290 // or there is no more services 291 // Or for example the typename can be used to detect object type if typedetection 292 // was also extended. 293 294 uno::Reference< embed::XEmbedObjectCreator > xOleEmbCreator( 295 m_xFactory->createInstance( 296 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLEEmbeddedObjectFactory" ) ), 297 uno::UNO_QUERY ); 298 if ( !xOleEmbCreator.is() ) 299 throw uno::RuntimeException(); // TODO: 300 301 xResult = xOleEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aTempMedDescr, lObjArgs ); 302 } 303 304 return xResult; 305 } 306 307 //------------------------------------------------------------------------- 308 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceUserInit( 309 const uno::Sequence< sal_Int8 >& aClassID, 310 const ::rtl::OUString& sClassName, 311 const uno::Reference< embed::XStorage >& xStorage, 312 const ::rtl::OUString& sEntName, 313 sal_Int32 nEntryConnectionMode, 314 const uno::Sequence< beans::PropertyValue >& aArgs, 315 const uno::Sequence< beans::PropertyValue >& aObjectArgs ) 316 throw ( lang::IllegalArgumentException, 317 io::IOException, 318 uno::Exception, 319 uno::RuntimeException) 320 { 321 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceUserInit" ); 322 323 uno::Reference< uno::XInterface > xResult; 324 325 if ( !xStorage.is() ) 326 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 327 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 328 3 ); 329 330 if ( !sEntName.getLength() ) 331 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 332 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 333 4 ); 334 335 ::rtl::OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID ); 336 uno::Reference< embed::XEmbedObjectFactory > xEmbFactory( 337 m_xFactory->createInstance( aEmbedFactory ), 338 uno::UNO_QUERY ); 339 if ( !xEmbFactory.is() ) 340 throw uno::RuntimeException(); // TODO: 341 342 return xEmbFactory->createInstanceUserInit( aClassID, 343 sClassName, 344 xStorage, 345 sEntName, 346 nEntryConnectionMode, 347 aArgs, 348 aObjectArgs ); 349 } 350 351 //------------------------------------------------------------------------- 352 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceLink( 353 const uno::Reference< embed::XStorage >& xStorage, 354 const ::rtl::OUString& sEntName, 355 const uno::Sequence< beans::PropertyValue >& aMediaDescr, 356 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 357 throw ( lang::IllegalArgumentException, 358 io::IOException, 359 uno::Exception, 360 uno::RuntimeException ) 361 { 362 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceLink" ); 363 364 uno::Reference< uno::XInterface > xResult; 365 366 uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr ); 367 368 // check if there is URL, URL must exist 369 ::rtl::OUString aURL; 370 for ( sal_Int32 nInd = 0; nInd < aTempMedDescr.getLength(); nInd++ ) 371 if ( aTempMedDescr[nInd].Name.equalsAscii( "URL" ) ) 372 aTempMedDescr[nInd].Value >>= aURL; 373 374 if ( !aURL.getLength() ) 375 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No URL for the link is provided!\n" ), 376 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), 377 3 ); 378 379 ::rtl::OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, sal_False ); 380 381 if ( aFilterName.getLength() ) 382 { 383 // the object can be loaded by one of the office application 384 uno::Reference< embed::XLinkCreator > xOOoLinkCreator( 385 m_xFactory->createInstance( 386 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OOoEmbeddedObjectFactory" ) ), 387 uno::UNO_QUERY ); 388 if ( !xOOoLinkCreator.is() ) 389 throw uno::RuntimeException(); // TODO: 390 391 xResult = xOOoLinkCreator->createInstanceLink( xStorage, 392 sEntName, 393 aTempMedDescr, 394 lObjArgs ); 395 } 396 else 397 { 398 // must be an OLE link 399 400 // TODO: in future, when more object types are possible this place seems 401 // to be a weak one, probably configuration must provide a type detection service 402 // for every factory, so any file could go through services until it is recognized 403 // or there is no more services 404 // Or for example the typename can be used to detect object type if typedetection 405 // was also extended. 406 407 if ( !xStorage.is() ) 408 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), 409 uno::Reference< uno::XInterface >( 410 static_cast< ::cppu::OWeakObject* >(this) ), 411 3 ); 412 413 if ( !sEntName.getLength() ) 414 throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), 415 uno::Reference< uno::XInterface >( 416 static_cast< ::cppu::OWeakObject* >(this) ), 417 4 ); 418 419 uno::Reference< embed::XLinkCreator > xLinkCreator( 420 m_xFactory->createInstance( 421 ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLEEmbeddedObjectFactory" ) ), 422 uno::UNO_QUERY ); 423 if ( !xLinkCreator.is() ) 424 throw uno::RuntimeException(); // TODO: 425 426 xResult = xLinkCreator->createInstanceLink( xStorage, sEntName, aTempMedDescr, lObjArgs ); 427 } 428 429 return xResult; 430 } 431 432 //------------------------------------------------------------------------- 433 uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceLinkUserInit( 434 const uno::Sequence< sal_Int8 >& aClassID, 435 const ::rtl::OUString& aClassName, 436 const uno::Reference< embed::XStorage >& xStorage, 437 const ::rtl::OUString& sEntName, 438 const uno::Sequence< beans::PropertyValue >& lArguments, 439 const uno::Sequence< beans::PropertyValue >& lObjArgs ) 440 throw ( lang::IllegalArgumentException, 441 io::IOException, 442 uno::Exception, 443 uno::RuntimeException ) 444 { 445 RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) UNOEmbeddedObjectCreator::createInstanceLinkUserInit" ); 446 447 uno::Reference< uno::XInterface > xResult; 448 449 ::rtl::OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID ); 450 uno::Reference< embed::XLinkFactory > xLinkFactory( 451 m_xFactory->createInstance( aEmbedFactory ), 452 uno::UNO_QUERY ); 453 if ( !xLinkFactory.is() ) 454 throw uno::RuntimeException(); // TODO: 455 456 return xLinkFactory->createInstanceLinkUserInit( aClassID, 457 aClassName, 458 xStorage, 459 sEntName, 460 lArguments, 461 lObjArgs ); 462 463 } 464 465 //------------------------------------------------------------------------- 466 ::rtl::OUString SAL_CALL UNOEmbeddedObjectCreator::getImplementationName() 467 throw ( uno::RuntimeException ) 468 { 469 return impl_staticGetImplementationName(); 470 } 471 472 //------------------------------------------------------------------------- 473 sal_Bool SAL_CALL UNOEmbeddedObjectCreator::supportsService( const ::rtl::OUString& ServiceName ) 474 throw ( uno::RuntimeException ) 475 { 476 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); 477 478 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 479 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) 480 return sal_True; 481 482 return sal_False; 483 } 484 485 //------------------------------------------------------------------------- 486 uno::Sequence< ::rtl::OUString > SAL_CALL UNOEmbeddedObjectCreator::getSupportedServiceNames() 487 throw ( uno::RuntimeException ) 488 { 489 return impl_staticGetSupportedServiceNames(); 490 } 491 492