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/container/XNameContainer.hpp>
21 #include <com/sun/star/xml/sax/Parser.hpp>
22 #include <com/sun/star/xml/sax/InputSource.hpp>
23 #include <com/sun/star/xml/sax/Writer.hpp>
24 #include <com/sun/star/io/XOutputStream.hpp>
25 #include <com/sun/star/io/XInputStream.hpp>
26 #include <com/sun/star/io/XInputStreamProvider.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
29 #include <com/sun/star/resource/StringResourceWithStorage.hpp>
30 #include <com/sun/star/resource/StringResourceWithLocation.hpp>
31 #include <com/sun/star/document/GraphicStorageHandler.hpp>
32 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
33 #include <dlgcont.hxx>
34 #include <comphelper/fileformat.h>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <o3tl/temporary.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
41 #include <xmlscript/xmldlg_imexp.hxx>
42 #include <sot/storage.hxx>
43 #include <svtools/sfxecode.hxx>
44 #include <svtools/ehdl.hxx>
45 #include <vcl/GraphicObject.hxx>
46 #include <i18nlangtag/languagetag.hxx>
51 using namespace com::sun::star::document
;
52 using namespace com::sun::star::container
;
53 using namespace com::sun::star::io
;
54 using namespace com::sun::star::uno
;
55 using namespace com::sun::star::ucb
;
56 using namespace com::sun::star::lang
;
57 using namespace com::sun::star::xml::sax
;
58 using namespace com::sun::star
;
61 using com::sun::star::uno::Reference
;
64 // Implementation class SfxDialogLibraryContainer
66 OUString
SfxDialogLibraryContainer::getInfoFileName() const
68 static constexpr OUStringLiteral dialog
= u
"dialog";
71 OUString
SfxDialogLibraryContainer::getOldInfoFileName() const
73 static constexpr OUStringLiteral dialogs
= u
"dialogs";
76 OUString
SfxDialogLibraryContainer::getLibElementFileExtension() const
78 static constexpr OUStringLiteral xdl
= u
"xdl";
81 OUString
SfxDialogLibraryContainer::getLibrariesDir() const
83 static constexpr OUStringLiteral Dialogs
= u
"Dialogs";
88 SfxDialogLibraryContainer::SfxDialogLibraryContainer()
90 // all initialisation has to be done
91 // by calling XInitialization::initialize
94 SfxDialogLibraryContainer::SfxDialogLibraryContainer( const uno::Reference
< embed::XStorage
>& xStorage
)
96 init(OUString(), xStorage
, o3tl::temporary(std::unique_lock(m_aMutex
)));
99 // Methods to get library instances of the correct type
100 rtl::Reference
<SfxLibrary
> SfxDialogLibraryContainer::implCreateLibrary( const OUString
& aName
)
102 return new SfxDialogLibrary( maModifiable
, aName
, mxSFI
, this );
105 rtl::Reference
<SfxLibrary
> SfxDialogLibraryContainer::implCreateLibraryLink
106 ( const OUString
& aName
, const OUString
& aLibInfoFileURL
,
107 const OUString
& StorageURL
, bool ReadOnly
)
109 return new SfxDialogLibrary
110 ( maModifiable
, aName
, mxSFI
, aLibInfoFileURL
, StorageURL
, ReadOnly
, this );
113 Any
SfxDialogLibraryContainer::createEmptyLibraryElement()
115 Reference
< XInputStreamProvider
> xISP
;
121 bool SfxDialogLibraryContainer::isLibraryElementValid(const Any
& rElement
) const
123 return SfxDialogLibrary::containsValidDialog(rElement
);
126 static bool writeOasis2OOoLibraryElement(
127 const Reference
< XInputStream
>& xInput
, const Reference
< XOutputStream
>& xOutput
)
129 const Reference
< XComponentContext
>& xContext(
130 comphelper::getProcessComponentContext() );
132 Reference
< lang::XMultiComponentFactory
> xSMgr(
133 xContext
->getServiceManager() );
135 Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
137 Reference
< xml::sax::XWriter
> xWriter
= xml::sax::Writer::create(xContext
);
139 xWriter
->setOutputStream( xOutput
);
141 Sequence
<Any
> aArgs
{ Any(xWriter
) };
142 Reference
< xml::sax::XDocumentHandler
> xHandler(
143 xSMgr
->createInstanceWithArgumentsAndContext(
144 u
"com.sun.star.comp.Oasis2OOoTransformer"_ustr
,
148 xParser
->setDocumentHandler( xHandler
);
150 xml::sax::InputSource source
;
151 source
.aInputStream
= xInput
;
152 source
.sSystemId
= "virtual file";
154 xParser
->parseStream( source
);
159 void SfxDialogLibraryContainer::writeLibraryElement
161 const Reference
< XNameContainer
>& xLib
,
162 const OUString
& aElementName
,
163 const Reference
< XOutputStream
>& xOutput
166 Any aElement
= xLib
->getByName( aElementName
);
167 Reference
< XInputStreamProvider
> xISP
;
172 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
174 bool bComplete
= false;
175 if ( mbOasis2OOoFormat
)
177 bComplete
= writeOasis2OOoLibraryElement( xInput
, xOutput
);
182 Sequence
< sal_Int8
> bytes
;
183 sal_Int32 nRead
= xInput
->readBytes( bytes
, xInput
->available() );
187 xOutput
->writeBytes( bytes
);
189 nRead
= xInput
->readBytes( bytes
, 1024 );
194 xInput
->closeInput();
197 void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference
< embed::XStorage
>& xStorage
)
199 LibraryContainerMethodGuard
aGuard( *this );
200 mbOasis2OOoFormat
= false;
202 if ( mxStorage
.is() && xStorage
.is() )
206 tools::Long nSource
= SotStorage::GetVersion( mxStorage
);
207 tools::Long nTarget
= SotStorage::GetVersion( xStorage
);
209 if ( nSource
== SOFFICE_FILEFORMAT_CURRENT
&&
210 nTarget
!= SOFFICE_FILEFORMAT_CURRENT
)
212 mbOasis2OOoFormat
= true;
215 catch (const Exception
& )
217 TOOLS_WARN_EXCEPTION("basic", "");
218 // if we cannot get the version then the
219 // Oasis2OOoTransformer will not be used
224 SfxLibraryContainer::storeLibrariesToStorage( xStorage
);
226 // we need to export out any embedded image object(s)
227 // associated with any Dialogs. First, we need to actually gather any such urls
228 // for each dialog in this container
229 const Sequence
< OUString
> sLibraries
= getElementNames();
230 for ( const OUString
& rName
: sLibraries
)
232 loadLibrary( rName
);
233 Reference
< XNameContainer
> xLib
;
234 getByName( rName
) >>= xLib
;
237 Sequence
< OUString
> sDialogs
= xLib
->getElementNames();
238 sal_Int32
nDialogs( sDialogs
.getLength() );
239 for ( sal_Int32 j
=0; j
< nDialogs
; ++j
)
241 // Each Dialog has an associated xISP
242 Reference
< io::XInputStreamProvider
> xISP
;
243 xLib
->getByName( sDialogs
[ j
] ) >>= xISP
;
246 Reference
< io::XInputStream
> xInput( xISP
->createInputStream() );
247 Reference
< XNameContainer
> xDialogModel(
248 mxContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.awt.UnoControlDialogModel"_ustr
, mxContext
),
250 ::xmlscript::importDialogModel( xInput
, xDialogModel
, mxContext
, mxOwnerDocument
);
251 std::vector
<uno::Reference
<graphic::XGraphic
>> vxGraphicList
;
252 vcl::graphic::SearchForGraphics(Reference
<XInterface
>(xDialogModel
, UNO_QUERY
), vxGraphicList
);
253 if (!vxGraphicList
.empty())
255 // Export the images to the storage
256 Reference
<document::XGraphicStorageHandler
> xGraphicStorageHandler
;
257 xGraphicStorageHandler
.set(document::GraphicStorageHandler::createWithStorage(mxContext
, xStorage
));
258 if (xGraphicStorageHandler
.is())
260 for (uno::Reference
<graphic::XGraphic
> const & rxGraphic
: vxGraphicList
)
262 xGraphicStorageHandler
->saveGraphic(rxGraphic
);
266 Reference
< XComponent
> xDialogModelComp(xDialogModel
, UNO_QUERY
);
267 if (xDialogModelComp
)
268 xDialogModelComp
->dispose();
273 mbOasis2OOoFormat
= false;
277 Any
SfxDialogLibraryContainer::importLibraryElement
278 ( const Reference
< XNameContainer
>& /*xLib*/,
279 const OUString
& /*aElementName */, const OUString
& aFile
,
280 const uno::Reference
< io::XInputStream
>& xElementStream
)
284 // TODO: Member because later it will be a component
285 //Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() );
288 // OSL_FAIL( "### couldn't get ProcessServiceFactory" );
292 Reference
< XParser
> xParser
= xml::sax::Parser::create( mxContext
);
294 Reference
< XNameContainer
> xDialogModel(
295 mxContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.awt.UnoControlDialogModel"_ustr
, mxContext
),
297 if( !xDialogModel
.is() )
299 OSL_FAIL( "### couldn't create com.sun.star.awt.UnoControlDialogModel component" );
303 // Read from storage?
304 bool bStorage
= xElementStream
.is();
305 Reference
< XInputStream
> xInput
;
309 xInput
= xElementStream
;
315 xInput
= mxSFI
->openFileRead( aFile
);
317 catch(const Exception
& )
318 //catch( Exception& e )
321 //throw WrappedTargetException( e );
328 source
.aInputStream
= std::move(xInput
);
329 source
.sSystemId
= aFile
;
333 xParser
->setDocumentHandler( ::xmlscript::importDialogModel( xDialogModel
, mxContext
, mxOwnerDocument
) );
334 xParser
->parseStream( source
);
336 catch(const Exception
& )
338 OSL_FAIL( "Parsing error" );
339 SfxErrorContext
aEc( ERRCTX_SFX_LOADBASIC
, aFile
);
340 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
344 // Create InputStream, TODO: Implement own InputStreamProvider
345 // to avoid creating the DialogModel here!
346 Reference
< XInputStreamProvider
> xISP
= ::xmlscript::exportDialogModel( xDialogModel
, mxContext
, mxOwnerDocument
);
349 Reference
< XComponent
> xDialogModelComp(xDialogModel
, UNO_QUERY
);
350 if (xDialogModelComp
)
351 xDialogModelComp
->dispose();
356 void SfxDialogLibraryContainer::importFromOldStorage( const OUString
& )
358 // Nothing to do here, old dialogs cannot be imported
361 rtl::Reference
<SfxLibraryContainer
> SfxDialogLibraryContainer::createInstanceImpl()
363 return new SfxDialogLibraryContainer();
366 constexpr OUString aResourceFileNameBase
= u
"DialogStrings"_ustr
;
367 constexpr OUString aResourceFileCommentBase
= u
"# Strings for Dialog Library "_ustr
;
370 Reference
< css::resource::XStringResourcePersistence
>
371 SfxDialogLibraryContainer::implCreateStringResource( SfxDialogLibrary
* pDialogLibrary
)
373 Reference
< resource::XStringResourcePersistence
> xRet
;
374 OUString aLibName
= pDialogLibrary
->getName();
375 bool bReadOnly
= pDialogLibrary
->mbReadOnly
;
378 ::com::sun ::star::lang::Locale aLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
380 OUString aComment
= aResourceFileCommentBase
+ aLibName
;
382 bool bStorage
= mxStorage
.is();
385 uno::Reference
< embed::XStorage
> xLibrariesStor
;
386 uno::Reference
< embed::XStorage
> xLibraryStor
;
388 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
389 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
390 if ( !xLibrariesStor
.is() )
391 throw uno::RuntimeException(u
"null returned from openStorageElement"_ustr
,getXWeak());
393 xLibraryStor
= xLibrariesStor
->openStorageElement( aLibName
, embed::ElementModes::READ
);
394 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
395 if ( !xLibraryStor
.is() )
396 throw uno::RuntimeException(u
"null returned from openStorageElement"_ustr
,getXWeak());
398 catch(const uno::Exception
& )
400 // Something went wrong while trying to get the storage library.
401 // Return an object that supports StringResourceWithStorage, give it a storage location later.
402 xRet
= Reference
< resource::XStringResourcePersistence
>(
403 mxContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.resource.StringResourceWithStorage"_ustr
, mxContext
),
408 xRet
= resource::StringResourceWithStorage::create(mxContext
, xLibraryStor
, bReadOnly
, aLocale
, aResourceFileNameBase
, aComment
);
412 OUString aLocation
= createAppLibraryFolder( pDialogLibrary
, aLibName
);
413 // TODO: Real handler?
414 Reference
< task::XInteractionHandler
> xDummyHandler
;
416 xRet
= resource::StringResourceWithLocation::create(mxContext
, aLocation
, bReadOnly
, aLocale
, aResourceFileNameBase
, aComment
, xDummyHandler
);
422 void SfxDialogLibraryContainer::onNewRootStorage()
424 // the library container is not modified, go through the libraries and check whether they are modified
425 Sequence
< OUString
> aNames
= maNameContainer
.getElementNames();
426 const OUString
* pNames
= aNames
.getConstArray();
427 sal_Int32 nNameCount
= aNames
.getLength();
429 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
431 OUString aName
= pNames
[ i
];
432 SfxDialogLibrary
* pDialogLibrary
= static_cast<SfxDialogLibrary
*>( getImplLib( aName
) );
434 Reference
< resource::XStringResourcePersistence
> xStringResourcePersistence
=
435 pDialogLibrary
->getStringResourcePersistence();
437 if( xStringResourcePersistence
.is() )
439 Reference
< embed::XStorage
> xLibrariesStor
;
440 Reference
< embed::XStorage
> xLibraryStor
;
442 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READWRITE
);
443 if ( !xLibrariesStor
.is() )
444 throw uno::RuntimeException(u
"null returned from openStorageElement"_ustr
,getXWeak());
446 OUString aLibName
= pDialogLibrary
->getName();
447 xLibraryStor
= xLibrariesStor
->openStorageElement( aLibName
, embed::ElementModes::READWRITE
);
448 if ( !xLibraryStor
.is() )
449 throw uno::RuntimeException(u
"null returned from openStorageElement"_ustr
,getXWeak());
451 Reference
< resource::XStringResourceWithStorage
>
452 xStringResourceWithStorage( xStringResourcePersistence
, UNO_QUERY
);
453 if( xStringResourceWithStorage
.is() )
454 xStringResourceWithStorage
->setStorage( xLibraryStor
);
456 catch(const uno::Exception
& )
458 // TODO: Error handling?
465 SfxDialogLibraryContainer:: HasExecutableCode( const OUString
& /*Library*/ )
467 return false; // dialog library has no executable code
472 OUString SAL_CALL
SfxDialogLibraryContainer::getImplementationName( )
474 return u
"com.sun.star.comp.sfx2.DialogLibraryContainer"_ustr
;
477 Sequence
< OUString
> SAL_CALL
SfxDialogLibraryContainer::getSupportedServiceNames( )
479 return {u
"com.sun.star.script.DocumentDialogLibraryContainer"_ustr
,
480 u
"com.sun.star.script.DialogLibraryContainer"_ustr
}; // for compatibility
483 // Implementation class SfxDialogLibrary
486 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper
& _rModifiable
,
488 const Reference
< XSimpleFileAccess3
>& xSFI
,
489 SfxDialogLibraryContainer
* pParent
)
490 : SfxDialogLibrary_BASE(_rModifiable
, cppu::UnoType
<XInputStreamProvider
>::get(), xSFI
)
491 , m_pParent( pParent
)
492 , m_aName(std::move( aName
))
496 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper
& _rModifiable
,
498 const Reference
< XSimpleFileAccess3
>& xSFI
,
499 const OUString
& aLibInfoFileURL
,
500 const OUString
& aStorageURL
,
502 SfxDialogLibraryContainer
* pParent
)
503 : SfxDialogLibrary_BASE(_rModifiable
, cppu::UnoType
<XInputStreamProvider
>::get(),
504 xSFI
, aLibInfoFileURL
, aStorageURL
, ReadOnly
)
505 , m_pParent( pParent
)
506 , m_aName(std::move( aName
))
510 // Provide modify state including resources
511 bool SfxDialogLibrary::isModified()
513 bool bRet
= implIsModified();
515 if( !bRet
&& m_xStringResourcePersistence
.is() )
516 bRet
= m_xStringResourcePersistence
->isModified();
517 // else: Resources not accessed so far -> not modified
522 void SfxDialogLibrary::storeResources()
524 if( m_xStringResourcePersistence
.is() )
525 m_xStringResourcePersistence
->store();
528 void SfxDialogLibrary::storeResourcesAsURL
529 ( const OUString
& URL
, const OUString
& NewName
)
531 OUString
aComment(aResourceFileCommentBase
);
535 if( m_xStringResourcePersistence
.is() )
537 m_xStringResourcePersistence
->setComment( aComment
);
539 Reference
< resource::XStringResourceWithLocation
>
540 xStringResourceWithLocation( m_xStringResourcePersistence
, UNO_QUERY
);
541 if( xStringResourceWithLocation
.is() )
542 xStringResourceWithLocation
->storeAsURL( URL
);
546 void SfxDialogLibrary::storeResourcesToURL( const OUString
& URL
,
547 const Reference
< task::XInteractionHandler
>& xHandler
)
549 OUString aComment
= aResourceFileCommentBase
+ m_aName
;
551 if( m_xStringResourcePersistence
.is() )
553 m_xStringResourcePersistence
->storeToURL
554 ( URL
, aResourceFileNameBase
, aComment
, xHandler
);
558 void SfxDialogLibrary::storeResourcesToStorage( const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
560 OUString aComment
= aResourceFileCommentBase
+ m_aName
;
562 if( m_xStringResourcePersistence
.is() )
564 m_xStringResourcePersistence
->storeToStorage
565 ( xStorage
, aResourceFileNameBase
, aComment
);
570 // XStringResourceSupplier
571 Reference
< resource::XStringResourceResolver
>
572 SAL_CALL
SfxDialogLibrary::getStringResource( )
574 if( !m_xStringResourcePersistence
.is() )
575 m_xStringResourcePersistence
= m_pParent
->implCreateStringResource( this );
577 return m_xStringResourcePersistence
;
580 bool SfxDialogLibrary::containsValidDialog( const css::uno::Any
& aElement
)
582 Reference
< XInputStreamProvider
> xISP
;
587 bool SfxDialogLibrary::isLibraryElementValid(const css::uno::Any
& rElement
) const
589 return SfxDialogLibrary::containsValidDialog(rElement
);
594 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
595 com_sun_star_comp_sfx2_DialogLibraryContainer_get_implementation(css::uno::XComponentContext
*,
596 css::uno::Sequence
<css::uno::Any
> const &)
598 return cppu::acquire(new basic::SfxDialogLibraryContainer());
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */