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