build fix
[LibreOffice.git] / embeddedobj / source / general / xcreator.cxx
blob6e171f21ebc3e23cec813fe8092c4e79d96d26b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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";
48 return aRet;
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,
72 io::IOException,
73 uno::Exception,
74 uno::RuntimeException, std::exception)
76 uno::Reference< uno::XInterface > xResult;
78 if ( !xStorage.is() )
79 throw lang::IllegalArgumentException( "No parent storage is provided!",
80 static_cast< ::cppu::OWeakObject* >(this),
81 3 );
83 if ( sEntName.isEmpty() )
84 throw lang::IllegalArgumentException( "Empty element name is provided!",
85 static_cast< ::cppu::OWeakObject* >(this),
86 4 );
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,
115 io::IOException,
116 uno::Exception,
117 uno::RuntimeException, std::exception)
119 if ( !xStorage.is() )
120 throw lang::IllegalArgumentException( "No parent storage is provided!",
121 static_cast< ::cppu::OWeakObject* >(this),
122 1 );
124 if ( sEntName.isEmpty() )
125 throw lang::IllegalArgumentException( "Empty element name is provided!",
126 static_cast< ::cppu::OWeakObject* >(this),
127 2 );
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();
137 OUString aMediaType;
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();
149 try {
150 uno::Any aAny = xPropSet->getPropertyValue("MediaType");
151 aAny >>= aMediaType;
153 catch ( const uno::Exception& )
157 try {
158 uno::Reference< lang::XComponent > xComp( xSubStorage, uno::UNO_QUERY );
159 if ( xComp.is() )
160 xComp->dispose();
162 catch ( const uno::Exception& )
166 else
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();
181 try {
182 uno::Any aAny = xPropSet->getPropertyValue("MediaType");
183 aAny >>= aMediaType;
184 if ( aMediaType == "application/vnd.sun.star.oleobject" )
185 aEmbedFactory = "com.sun.star.embed.OLEEmbeddedObjectFactory";
187 catch ( const uno::Exception& )
191 try {
192 uno::Reference< lang::XComponent > xComp( xSubStream, uno::UNO_QUERY );
193 if ( xComp.is() )
194 xComp->dispose();
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 );
220 if ( xEmbFact.is() )
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 );
228 return xResult;
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,
238 io::IOException,
239 uno::Exception,
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),
247 1 );
249 if ( sEntName.isEmpty() )
250 throw lang::IllegalArgumentException( "Empty element name is provided!",
251 static_cast< ::cppu::OWeakObject* >(this),
252 2 );
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,
267 sEntName,
268 aTempMedDescr,
269 lObjArgs );
271 else
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 );
288 return xResult;
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,
301 io::IOException,
302 uno::Exception,
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),
310 3 );
312 if ( sEntName.isEmpty() )
313 throw lang::IllegalArgumentException( "Empty element name is provided!",
314 static_cast< ::cppu::OWeakObject* >(this),
315 4 );
317 OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID );
318 uno::Reference< embed::XEmbedObjectFactory > xEmbFactory(
319 m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext),
320 uno::UNO_QUERY );
321 if ( !xEmbFactory.is() )
322 throw uno::RuntimeException(); // TODO:
324 return xEmbFactory->createInstanceUserInit( aClassID,
325 sClassName,
326 xStorage,
327 sEntName,
328 nEntryConnectionMode,
329 aArgs,
330 aObjectArgs );
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,
340 io::IOException,
341 uno::Exception,
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
349 OUString aURL;
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),
357 3 );
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,
368 sEntName,
369 aTempMedDescr,
370 lObjArgs );
372 else
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),
386 3 );
388 if ( sEntName.isEmpty() )
389 throw lang::IllegalArgumentException( "Empty element name is provided!",
390 static_cast< ::cppu::OWeakObject* >(this),
391 4 );
393 uno::Reference< embed::XEmbeddedObjectCreator > xLinkCreator =
394 embed::OLEEmbeddedObjectFactory::create( m_xContext);
396 xResult = xLinkCreator->createInstanceLink( xStorage, sEntName, aTempMedDescr, lObjArgs );
399 return xResult;
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: */