1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/ElementModes.hpp>
21 #include <com/sun/star/embed/EntryInitModes.hpp>
22 #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
23 #include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
24 #include <com/sun/star/embed/OLEEmbeddedObjectFactory.hpp>
25 #include <com/sun/star/embed/XLinkFactory.hpp>
26 #include <com/sun/star/document/XTypeDetection.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/container/XNameAccess.hpp>
30 #include <com/sun/star/lang/XComponent.hpp>
32 #include <comphelper/processfactory.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <comphelper/documentconstants.hxx>
36 #include <xcreator.hxx>
37 #include <dummyobject.hxx>
40 using namespace ::com::sun::star
;
43 uno::Sequence
< OUString
> SAL_CALL
UNOEmbeddedObjectCreator::impl_staticGetSupportedServiceNames()
45 uno::Sequence
< OUString
> aRet(2);
46 aRet
[0] = "com.sun.star.embed.EmbeddedObjectCreator";
47 aRet
[1] = "com.sun.star.comp.embed.EmbeddedObjectCreator";
52 OUString SAL_CALL
UNOEmbeddedObjectCreator::impl_staticGetImplementationName()
54 return OUString("com.sun.star.comp.embed.EmbeddedObjectCreator");
58 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::impl_staticCreateSelfInstance(
59 const uno::Reference
< lang::XMultiServiceFactory
>& xServiceManager
)
61 return uno::Reference
< uno::XInterface
>( *new UNOEmbeddedObjectCreator( comphelper::getComponentContext(xServiceManager
) ) );
65 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::createInstanceInitNew(
66 const uno::Sequence
< sal_Int8
>& aClassID
,
67 const OUString
& aClassName
,
68 const uno::Reference
< embed::XStorage
>& xStorage
,
69 const OUString
& sEntName
,
70 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
71 throw ( lang::IllegalArgumentException
,
74 uno::RuntimeException
, std::exception
)
76 uno::Reference
< uno::XInterface
> xResult
;
79 throw lang::IllegalArgumentException( "No parent storage is provided!",
80 static_cast< ::cppu::OWeakObject
* >(this),
83 if ( sEntName
.isEmpty() )
84 throw lang::IllegalArgumentException( "Empty element name is provided!",
85 static_cast< ::cppu::OWeakObject
* >(this),
88 OUString aEmbedFactory
= m_aConfigHelper
.GetFactoryNameByClassID( aClassID
);
89 if ( aEmbedFactory
.isEmpty() )
91 // use system fallback
92 // TODO: in future users factories can be tested
93 aEmbedFactory
= "com.sun.star.embed.OLEEmbeddedObjectFactory";
96 uno::Reference
< uno::XInterface
> xFact( m_xContext
->getServiceManager()->createInstanceWithContext(aEmbedFactory
, m_xContext
) );
97 uno::Reference
< embed::XEmbedObjectCreator
> xEmbCreator( xFact
, uno::UNO_QUERY
);
98 if ( xEmbCreator
.is() )
99 return xEmbCreator
->createInstanceInitNew( aClassID
, aClassName
, xStorage
, sEntName
, lObjArgs
);
101 uno::Reference
< embed::XEmbedObjectFactory
> xEmbFact( xFact
, uno::UNO_QUERY
);
102 if ( !xEmbFact
.is() )
103 throw uno::RuntimeException();
104 return xEmbFact
->createInstanceUserInit( aClassID
, aClassName
, xStorage
, sEntName
, embed::EntryInitModes::TRUNCATE_INIT
, uno::Sequence
< beans::PropertyValue
>(), lObjArgs
);
108 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::createInstanceInitFromEntry(
109 const uno::Reference
< embed::XStorage
>& xStorage
,
110 const OUString
& sEntName
,
111 const uno::Sequence
< beans::PropertyValue
>& aMedDescr
,
112 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
113 throw ( lang::IllegalArgumentException
,
114 container::NoSuchElementException
,
117 uno::RuntimeException
, std::exception
)
119 if ( !xStorage
.is() )
120 throw lang::IllegalArgumentException( "No parent storage is provided!",
121 static_cast< ::cppu::OWeakObject
* >(this),
124 if ( sEntName
.isEmpty() )
125 throw lang::IllegalArgumentException( "Empty element name is provided!",
126 static_cast< ::cppu::OWeakObject
* >(this),
129 uno::Reference
< container::XNameAccess
> xNameAccess( xStorage
, uno::UNO_QUERY
);
130 if ( !xNameAccess
.is() )
131 throw uno::RuntimeException(); //TODO
133 // detect entry existence
134 if ( !xNameAccess
->hasByName( sEntName
) )
135 throw container::NoSuchElementException();
138 OUString aEmbedFactory
;
139 if ( xStorage
->isStorageElement( sEntName
) )
141 // the object must be based on storage
142 uno::Reference
< embed::XStorage
> xSubStorage
=
143 xStorage
->openStorageElement( sEntName
, embed::ElementModes::READ
);
145 uno::Reference
< beans::XPropertySet
> xPropSet( xSubStorage
, uno::UNO_QUERY
);
146 if ( !xPropSet
.is() )
147 throw uno::RuntimeException();
150 uno::Any aAny
= xPropSet
->getPropertyValue("MediaType");
153 catch ( const uno::Exception
& )
158 uno::Reference
< lang::XComponent
> xComp( xSubStorage
, uno::UNO_QUERY
);
162 catch ( const uno::Exception
& )
168 // the object must be based on stream
169 // it means for now that this is an OLE object
171 // the object will be created as embedded object
172 // after it is loaded it can detect that it is a link
174 uno::Reference
< io::XStream
> xSubStream
=
175 xStorage
->openStreamElement( sEntName
, embed::ElementModes::READ
);
177 uno::Reference
< beans::XPropertySet
> xPropSet( xSubStream
, uno::UNO_QUERY
);
178 if ( !xPropSet
.is() )
179 throw uno::RuntimeException();
182 uno::Any aAny
= xPropSet
->getPropertyValue("MediaType");
184 if ( aMediaType
== "application/vnd.sun.star.oleobject" )
185 aEmbedFactory
= "com.sun.star.embed.OLEEmbeddedObjectFactory";
187 catch ( const uno::Exception
& )
192 uno::Reference
< lang::XComponent
> xComp( xSubStream
, uno::UNO_QUERY
);
196 catch ( const uno::Exception
& )
201 OSL_ENSURE( !aMediaType
.isEmpty(), "No media type is specified for the object!" );
202 if ( !aMediaType
.isEmpty() && aEmbedFactory
.isEmpty() )
204 aEmbedFactory
= m_aConfigHelper
.GetFactoryNameByMediaType( aMediaType
);
206 // If no factory is found, fall back to the FileFormatVersion=6200 filter, Base only has that.
207 if (aEmbedFactory
.isEmpty() && aMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII
)
208 aEmbedFactory
= m_aConfigHelper
.GetFactoryNameByMediaType(MIMETYPE_VND_SUN_XML_BASE_ASCII
);
211 if ( !aEmbedFactory
.isEmpty() )
213 uno::Reference
< uno::XInterface
> xFact
= m_xContext
->getServiceManager()->createInstanceWithContext(aEmbedFactory
, m_xContext
);
215 uno::Reference
< embed::XEmbedObjectCreator
> xEmbCreator( xFact
, uno::UNO_QUERY
);
216 if ( xEmbCreator
.is() )
217 return xEmbCreator
->createInstanceInitFromEntry( xStorage
, sEntName
, aMedDescr
, lObjArgs
);
219 uno::Reference
< embed::XEmbedObjectFactory
> xEmbFact( xFact
, uno::UNO_QUERY
);
221 return xEmbFact
->createInstanceUserInit( uno::Sequence
< sal_Int8
>(), OUString(), xStorage
, sEntName
, embed::EntryInitModes::DEFAULT_INIT
, aMedDescr
, lObjArgs
);
224 // the default object should be created, it will allow to store the contents on the next saving
225 uno::Reference
< uno::XInterface
> xResult( static_cast< cppu::OWeakObject
* >( new ODummyEmbeddedObject() ) );
226 uno::Reference
< embed::XEmbedPersist
> xPersist( xResult
, uno::UNO_QUERY_THROW
);
227 xPersist
->setPersistentEntry( xStorage
, sEntName
, embed::EntryInitModes::DEFAULT_INIT
, aMedDescr
, lObjArgs
);
232 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::createInstanceInitFromMediaDescriptor(
233 const uno::Reference
< embed::XStorage
>& xStorage
,
234 const OUString
& sEntName
,
235 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
,
236 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
237 throw ( lang::IllegalArgumentException
,
240 uno::RuntimeException
, std::exception
)
242 // TODO: use lObjArgs
244 if ( !xStorage
.is() )
245 throw lang::IllegalArgumentException( "No parent storage is provided!",
246 static_cast< ::cppu::OWeakObject
* >(this),
249 if ( sEntName
.isEmpty() )
250 throw lang::IllegalArgumentException( "Empty element name is provided!",
251 static_cast< ::cppu::OWeakObject
* >(this),
254 uno::Reference
< uno::XInterface
> xResult
;
255 uno::Sequence
< beans::PropertyValue
> aTempMedDescr( aMediaDescr
);
257 // check if there is FilterName
258 OUString aFilterName
= m_aConfigHelper
.UpdateMediaDescriptorWithFilterName( aTempMedDescr
, false );
260 if ( !aFilterName
.isEmpty() )
262 // the object can be loaded by one of the office application
263 uno::Reference
< embed::XEmbeddedObjectCreator
> xOOoEmbCreator
=
264 embed::OOoEmbeddedObjectFactory::create( m_xContext
);
266 xResult
= xOOoEmbCreator
->createInstanceInitFromMediaDescriptor( xStorage
,
273 // must be an OLE object
275 // TODO: in future, when more object types are possible this place seems
276 // to be a weak one, probably configuration must provide a type detection service
277 // for every factory, so any file could go through services until it is recognized
278 // or there is no more services
279 // Or for example the typename can be used to detect object type if typedetection
280 // was also extended.
282 uno::Reference
< embed::XEmbeddedObjectCreator
> xOleEmbCreator
=
283 embed::OLEEmbeddedObjectFactory::create( m_xContext
);
285 xResult
= xOleEmbCreator
->createInstanceInitFromMediaDescriptor( xStorage
, sEntName
, aTempMedDescr
, lObjArgs
);
292 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::createInstanceUserInit(
293 const uno::Sequence
< sal_Int8
>& aClassID
,
294 const OUString
& sClassName
,
295 const uno::Reference
< embed::XStorage
>& xStorage
,
296 const OUString
& sEntName
,
297 sal_Int32 nEntryConnectionMode
,
298 const uno::Sequence
< beans::PropertyValue
>& aArgs
,
299 const uno::Sequence
< beans::PropertyValue
>& aObjectArgs
)
300 throw ( lang::IllegalArgumentException
,
303 uno::RuntimeException
, std::exception
)
305 uno::Reference
< uno::XInterface
> xResult
;
307 if ( !xStorage
.is() )
308 throw lang::IllegalArgumentException( "No parent storage is provided!",
309 static_cast< ::cppu::OWeakObject
* >(this),
312 if ( sEntName
.isEmpty() )
313 throw lang::IllegalArgumentException( "Empty element name is provided!",
314 static_cast< ::cppu::OWeakObject
* >(this),
317 OUString aEmbedFactory
= m_aConfigHelper
.GetFactoryNameByClassID( aClassID
);
318 uno::Reference
< embed::XEmbedObjectFactory
> xEmbFactory(
319 m_xContext
->getServiceManager()->createInstanceWithContext(aEmbedFactory
, m_xContext
),
321 if ( !xEmbFactory
.is() )
322 throw uno::RuntimeException(); // TODO:
324 return xEmbFactory
->createInstanceUserInit( aClassID
,
328 nEntryConnectionMode
,
334 uno::Reference
< uno::XInterface
> SAL_CALL
UNOEmbeddedObjectCreator::createInstanceLink(
335 const uno::Reference
< embed::XStorage
>& xStorage
,
336 const OUString
& sEntName
,
337 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
,
338 const uno::Sequence
< beans::PropertyValue
>& lObjArgs
)
339 throw ( lang::IllegalArgumentException
,
342 uno::RuntimeException
, std::exception
)
344 uno::Reference
< uno::XInterface
> xResult
;
346 uno::Sequence
< beans::PropertyValue
> aTempMedDescr( aMediaDescr
);
348 // check if there is URL, URL must exist
350 for ( sal_Int32 nInd
= 0; nInd
< aTempMedDescr
.getLength(); nInd
++ )
351 if ( aTempMedDescr
[nInd
].Name
== "URL" )
352 aTempMedDescr
[nInd
].Value
>>= aURL
;
354 if ( aURL
.isEmpty() )
355 throw lang::IllegalArgumentException( "No URL for the link is provided!",
356 static_cast< ::cppu::OWeakObject
* >(this),
359 OUString aFilterName
= m_aConfigHelper
.UpdateMediaDescriptorWithFilterName( aTempMedDescr
, false );
361 if ( !aFilterName
.isEmpty() )
363 // the object can be loaded by one of the office application
364 uno::Reference
< embed::XEmbeddedObjectCreator
> xOOoLinkCreator
=
365 embed::OOoEmbeddedObjectFactory::create( m_xContext
);
367 xResult
= xOOoLinkCreator
->createInstanceLink( xStorage
,
374 // must be an OLE link
376 // TODO: in future, when more object types are possible this place seems
377 // to be a weak one, probably configuration must provide a type detection service
378 // for every factory, so any file could go through services until it is recognized
379 // or there is no more services
380 // Or for example the typename can be used to detect object type if typedetection
381 // was also extended.
383 if ( !xStorage
.is() )
384 throw lang::IllegalArgumentException( "No parent storage is provided!",
385 static_cast< ::cppu::OWeakObject
* >(this),
388 if ( sEntName
.isEmpty() )
389 throw lang::IllegalArgumentException( "Empty element name is provided!",
390 static_cast< ::cppu::OWeakObject
* >(this),
393 uno::Reference
< embed::XEmbeddedObjectCreator
> xLinkCreator
=
394 embed::OLEEmbeddedObjectFactory::create( m_xContext
);
396 xResult
= xLinkCreator
->createInstanceLink( xStorage
, sEntName
, aTempMedDescr
, lObjArgs
);
402 OUString SAL_CALL
UNOEmbeddedObjectCreator::getImplementationName()
403 throw ( uno::RuntimeException
, std::exception
)
405 return impl_staticGetImplementationName();
408 sal_Bool SAL_CALL
UNOEmbeddedObjectCreator::supportsService( const OUString
& ServiceName
)
409 throw ( uno::RuntimeException
, std::exception
)
411 return cppu::supportsService(this, ServiceName
);
414 uno::Sequence
< OUString
> SAL_CALL
UNOEmbeddedObjectCreator::getSupportedServiceNames()
415 throw ( uno::RuntimeException
, std::exception
)
417 return impl_staticGetSupportedServiceNames();
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */