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/embed/ElementModes.hpp>
27 #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
28 #include <com/sun/star/io/XActiveDataSource.hpp>
29 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
30 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
31 #include <com/sun/star/resource/StringResourceWithStorage.hpp>
32 #include <com/sun/star/resource/StringResourceWithLocation.hpp>
33 #include <com/sun/star/document/GraphicObjectResolver.hpp>
34 #include "dlgcont.hxx"
35 #include <comphelper/processfactory.hxx>
36 #include <unotools/streamwrap.hxx>
37 #include <osl/mutex.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
41 #include <unotools/pathoptions.hxx>
42 #include <xmlscript/xmldlg_imexp.hxx>
43 #include <cppuhelper/factory.hxx>
44 #include <svtools/sfxecode.hxx>
45 #include <svtools/ehdl.hxx>
46 #include <svtools/grfmgr.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::script
;
58 using namespace com::sun::star::xml::sax
;
59 using namespace com::sun::star
;
63 using com::sun::star::uno::Reference
;
66 // Implementation class SfxDialogLibraryContainer
68 const sal_Char
* SAL_CALL
SfxDialogLibraryContainer::getInfoFileName() const { return "dialog"; }
69 const sal_Char
* SAL_CALL
SfxDialogLibraryContainer::getOldInfoFileName() const { return "dialogs"; }
70 const sal_Char
* SAL_CALL
SfxDialogLibraryContainer::getLibElementFileExtension() const { return "xdl"; }
71 const sal_Char
* SAL_CALL
SfxDialogLibraryContainer::getLibrariesDir() const { return "Dialogs"; }
74 SfxDialogLibraryContainer::SfxDialogLibraryContainer()
76 // all initialisation has to be done
77 // by calling XInitialization::initialize
80 SfxDialogLibraryContainer::SfxDialogLibraryContainer( const uno::Reference
< embed::XStorage
>& xStorage
)
82 init( OUString(), xStorage
);
85 // Methods to get library instances of the correct type
86 SfxLibrary
* SfxDialogLibraryContainer::implCreateLibrary( const OUString
& aName
)
88 SfxLibrary
* pRet
= new SfxDialogLibrary( maModifiable
, aName
, mxContext
, mxSFI
, this );
92 SfxLibrary
* SfxDialogLibraryContainer::implCreateLibraryLink
93 ( const OUString
& aName
, const OUString
& aLibInfoFileURL
,
94 const OUString
& StorageURL
, bool ReadOnly
)
96 SfxLibrary
* pRet
= new SfxDialogLibrary
97 ( maModifiable
, aName
, mxContext
, mxSFI
, aLibInfoFileURL
, StorageURL
, ReadOnly
, this );
101 Any SAL_CALL
SfxDialogLibraryContainer::createEmptyLibraryElement()
103 Reference
< XInputStreamProvider
> xISP
;
109 bool SAL_CALL
SfxDialogLibraryContainer::isLibraryElementValid(const Any
& rElement
) const
111 return SfxDialogLibrary::containsValidDialog(rElement
);
114 bool writeOasis2OOoLibraryElement(
115 Reference
< XInputStream
> xInput
, Reference
< XOutputStream
> xOutput
)
117 Reference
< XComponentContext
> xContext(
118 comphelper::getProcessComponentContext() );
120 Reference
< lang::XMultiComponentFactory
> xSMgr(
121 xContext
->getServiceManager() );
123 Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
125 Reference
< xml::sax::XWriter
> xWriter
= xml::sax::Writer::create(xContext
);
127 xWriter
->setOutputStream( xOutput
);
129 Sequence
<Any
> aArgs( 1 );
130 aArgs
[0] <<= xWriter
;
132 Reference
< xml::sax::XDocumentHandler
> xHandler(
133 xSMgr
->createInstanceWithArgumentsAndContext(
134 OUString("com.sun.star.comp.Oasis2OOoTransformer" ) ,
138 xParser
->setDocumentHandler( xHandler
);
140 xml::sax::InputSource source
;
141 source
.aInputStream
= xInput
;
142 source
.sSystemId
= "virtual file";
144 xParser
->parseStream( source
);
149 void SAL_CALL
SfxDialogLibraryContainer::writeLibraryElement
151 const Reference
< XNameContainer
>& xLib
,
152 const OUString
& aElementName
,
153 const Reference
< XOutputStream
>& xOutput
157 Any aElement
= xLib
->getByName( aElementName
);
158 Reference
< XInputStreamProvider
> xISP
;
163 Reference
< XInputStream
> xInput( xISP
->createInputStream() );
165 bool bComplete
= false;
166 if ( mbOasis2OOoFormat
)
168 bComplete
= writeOasis2OOoLibraryElement( xInput
, xOutput
);
173 Sequence
< sal_Int8
> bytes
;
174 sal_Int32 nRead
= xInput
->readBytes( bytes
, xInput
->available() );
178 xOutput
->writeBytes( bytes
);
180 nRead
= xInput
->readBytes( bytes
, 1024 );
185 xInput
->closeInput();
188 void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference
< embed::XStorage
>& xStorage
) throw ( RuntimeException
, WrappedTargetException
, std::exception
)
190 LibraryContainerMethodGuard
aGuard( *this );
191 mbOasis2OOoFormat
= false;
193 if ( mxStorage
.is() && xStorage
.is() )
197 long nSource
= SotStorage::GetVersion( mxStorage
);
198 long nTarget
= SotStorage::GetVersion( xStorage
);
200 if ( nSource
== SOFFICE_FILEFORMAT_CURRENT
&&
201 nTarget
!= SOFFICE_FILEFORMAT_CURRENT
)
203 mbOasis2OOoFormat
= true;
206 catch (const Exception
& )
208 // if we cannot get the version then the
209 // Oasis2OOoTransformer will not be used
214 SfxLibraryContainer::storeLibrariesToStorage( xStorage
);
216 // we need to export out any embedded image object(s)
217 // associated with any Dialogs. First, we need to actually gather any such urls
218 // for each dialog in this container
219 Sequence
< OUString
> sLibraries
= getElementNames();
220 for ( sal_Int32 i
=0; i
< sLibraries
.getLength(); ++i
)
222 loadLibrary( sLibraries
[ i
] );
223 Reference
< XNameContainer
> xLib
;
224 getByName( sLibraries
[ i
] ) >>= xLib
;
227 Sequence
< OUString
> sDialogs
= xLib
->getElementNames();
228 sal_Int32
nDialogs( sDialogs
.getLength() );
229 for ( sal_Int32 j
=0; j
< nDialogs
; ++j
)
231 // Each Dialog has an associated xISP
232 Reference
< io::XInputStreamProvider
> xISP
;
233 xLib
->getByName( sDialogs
[ j
] ) >>= xISP
;
236 Reference
< io::XInputStream
> xInput( xISP
->createInputStream() );
237 Reference
< XNameContainer
> xDialogModel(
238 mxContext
->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext
),
240 ::xmlscript::importDialogModel( xInput
, xDialogModel
, mxContext
, mxOwnerDocument
);
241 std::vector
< OUString
> vEmbeddedImageURLs
;
242 GraphicObject::InspectForGraphicObjectImageURL( Reference
<XInterface
>(xDialogModel
, UNO_QUERY
), vEmbeddedImageURLs
);
243 if ( !vEmbeddedImageURLs
.empty() )
245 // Export the images to the storage
246 Reference
< document::XGraphicObjectResolver
> xGraphicResolver
=
247 document::GraphicObjectResolver::createWithStorage( mxContext
, xStorage
);
248 std::vector
< OUString
>::iterator it
= vEmbeddedImageURLs
.begin();
249 std::vector
< OUString
>::iterator it_end
= vEmbeddedImageURLs
.end();
250 if ( xGraphicResolver
.is() )
252 for ( sal_Int32 count
= 0; it
!= it_end
; ++it
, ++count
)
253 xGraphicResolver
->resolveGraphicObjectURL( *it
);
260 mbOasis2OOoFormat
= false;
264 Any SAL_CALL
SfxDialogLibraryContainer::importLibraryElement
265 ( const Reference
< XNameContainer
>& /*xLib*/,
266 const OUString
& /*aElementName */, const OUString
& aFile
,
267 const uno::Reference
< io::XInputStream
>& xElementStream
)
271 // TODO: Member because later it will be a component
272 //Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() );
275 // OSL_FAIL( "### couldn't get ProcessServiceFactory\n" );
279 Reference
< XParser
> xParser
= xml::sax::Parser::create( mxContext
);
281 Reference
< XNameContainer
> xDialogModel(
282 mxContext
->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext
),
284 if( !xDialogModel
.is() )
286 OSL_FAIL( "### couldn't create com.sun.star.awt.UnoControlDialogModel component\n" );
290 // Read from storage?
291 bool bStorage
= xElementStream
.is();
292 Reference
< XInputStream
> xInput
;
296 xInput
= xElementStream
;
302 xInput
= mxSFI
->openFileRead( aFile
);
304 catch(const Exception
& )
305 //catch( Exception& e )
308 //throw WrappedTargetException( e );
315 source
.aInputStream
= xInput
;
316 source
.sSystemId
= aFile
;
320 xParser
->setDocumentHandler( ::xmlscript::importDialogModel( xDialogModel
, mxContext
, mxOwnerDocument
) );
321 xParser
->parseStream( source
);
323 catch(const Exception
& )
325 OSL_FAIL( "Parsing error\n" );
326 SfxErrorContext
aEc( ERRCTX_SFX_LOADBASIC
, aFile
);
327 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
331 // Create InputStream, TODO: Implement own InputStreamProvider
332 // to avoid creating the DialogModel here!
333 Reference
< XInputStreamProvider
> xISP
= ::xmlscript::exportDialogModel( xDialogModel
, mxContext
, mxOwnerDocument
);
338 void SAL_CALL
SfxDialogLibraryContainer::importFromOldStorage( const OUString
& )
340 // Nothing to do here, old dialogs cannot be imported
343 SfxLibraryContainer
* SfxDialogLibraryContainer::createInstanceImpl()
345 return new SfxDialogLibraryContainer();
348 const char aResourceFileNameBase
[] = "DialogStrings";
349 const char aResourceFileCommentBase
[] = "# Strings for Dialog Library ";
352 Reference
< ::com::sun::star::resource::XStringResourcePersistence
>
353 SfxDialogLibraryContainer::implCreateStringResource( SfxDialogLibrary
* pDialogLibrary
)
355 Reference
< resource::XStringResourcePersistence
> xRet
;
356 OUString aLibName
= pDialogLibrary
->getName();
357 bool bReadOnly
= pDialogLibrary
->mbReadOnly
;
360 ::com::sun ::star::lang::Locale aLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
362 OUString
aComment(aResourceFileCommentBase
);
363 aComment
+= aLibName
;
365 bool bStorage
= mxStorage
.is();
368 uno::Reference
< embed::XStorage
> xLibrariesStor
;
369 uno::Reference
< embed::XStorage
> xLibraryStor
;
371 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
372 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
373 if ( !xLibrariesStor
.is() )
374 throw uno::RuntimeException();
376 xLibraryStor
= xLibrariesStor
->openStorageElement( aLibName
, embed::ElementModes::READ
);
377 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
378 if ( !xLibraryStor
.is() )
379 throw uno::RuntimeException();
381 catch(const uno::Exception
& )
383 // TODO: Error handling?
387 xRet
= resource::StringResourceWithStorage::create(mxContext
, xLibraryStor
, bReadOnly
, aLocale
, OUString(aResourceFileNameBase
), aComment
);
391 OUString aLocation
= createAppLibraryFolder( pDialogLibrary
, aLibName
);
392 // TODO: Real handler?
393 Reference
< task::XInteractionHandler
> xDummyHandler
;
395 xRet
= resource::StringResourceWithLocation::create(mxContext
, aLocation
, bReadOnly
, aLocale
, OUString(aResourceFileNameBase
), aComment
, xDummyHandler
);
401 void SfxDialogLibraryContainer::onNewRootStorage()
403 // the library container is not modified, go through the libraries and check whether they are modified
404 Sequence
< OUString
> aNames
= maNameContainer
.getElementNames();
405 const OUString
* pNames
= aNames
.getConstArray();
406 sal_Int32 nNameCount
= aNames
.getLength();
408 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
410 OUString aName
= pNames
[ i
];
411 SfxDialogLibrary
* pDialogLibrary
= static_cast<SfxDialogLibrary
*>( getImplLib( aName
) );
413 Reference
< resource::XStringResourcePersistence
> xStringResourcePersistence
=
414 pDialogLibrary
->getStringResourcePersistence();
416 if( xStringResourcePersistence
.is() )
418 Reference
< embed::XStorage
> xLibrariesStor
;
419 Reference
< embed::XStorage
> xLibraryStor
;
421 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READWRITE
);
422 if ( !xLibrariesStor
.is() )
423 throw uno::RuntimeException();
425 OUString aLibName
= pDialogLibrary
->getName();
426 xLibraryStor
= xLibrariesStor
->openStorageElement( aLibName
, embed::ElementModes::READWRITE
);
427 if ( !xLibraryStor
.is() )
428 throw uno::RuntimeException();
430 Reference
< resource::XStringResourceWithStorage
>
431 xStringResourceWithStorage( xStringResourcePersistence
, UNO_QUERY
);
432 if( xStringResourceWithStorage
.is() )
433 xStringResourceWithStorage
->setStorage( xLibraryStor
);
435 catch(const uno::Exception
& )
437 // TODO: Error handling?
444 SfxDialogLibraryContainer:: HasExecutableCode( const OUString
& /*Library*/ ) throw (uno::RuntimeException
, std::exception
)
446 return sal_False
; // dialog library has no executable code
451 OUString SAL_CALL
SfxDialogLibraryContainer::getImplementationName( ) throw (RuntimeException
, std::exception
)
453 return OUString("com.sun.star.comp.sfx2.DialogLibraryContainer");
456 Sequence
< OUString
> SAL_CALL
SfxDialogLibraryContainer::getSupportedServiceNames( ) throw (RuntimeException
, std::exception
)
458 Sequence
< OUString
> aServiceNames( 2 );
459 aServiceNames
[0] = "com.sun.star.script.DocumentDialogLibraryContainer";
460 // plus, for compatibility:
461 aServiceNames
[1] = "com.sun.star.script.DialogLibraryContainer";
462 return aServiceNames
;
465 // Implementation class SfxDialogLibrary
468 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper
& _rModifiable
,
469 const OUString
& aName
,
470 const Reference
< XComponentContext
>& xContext
,
471 const Reference
< XSimpleFileAccess3
>& xSFI
,
472 SfxDialogLibraryContainer
* pParent
)
473 : SfxLibrary( _rModifiable
, cppu::UnoType
<XInputStreamProvider
>::get(), xContext
, xSFI
)
474 , m_pParent( pParent
)
479 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper
& _rModifiable
,
480 const OUString
& aName
,
481 const Reference
< XComponentContext
>& xContext
,
482 const Reference
< XSimpleFileAccess3
>& xSFI
,
483 const OUString
& aLibInfoFileURL
,
484 const OUString
& aStorageURL
,
486 SfxDialogLibraryContainer
* pParent
)
487 : SfxLibrary( _rModifiable
, cppu::UnoType
<XInputStreamProvider
>::get(),
488 xContext
, xSFI
, aLibInfoFileURL
, aStorageURL
, ReadOnly
)
489 , m_pParent( pParent
)
494 IMPLEMENT_FORWARD_XINTERFACE2( SfxDialogLibrary
, SfxLibrary
, SfxDialogLibrary_BASE
);
495 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxDialogLibrary
, SfxLibrary
, SfxDialogLibrary_BASE
);
497 // Provide modify state including resources
498 bool SfxDialogLibrary::isModified()
500 bool bRet
= implIsModified();
502 if( !bRet
&& m_xStringResourcePersistence
.is() )
503 bRet
= m_xStringResourcePersistence
->isModified();
504 // else: Resources not accessed so far -> not modified
509 void SfxDialogLibrary::storeResources()
511 if( m_xStringResourcePersistence
.is() )
512 m_xStringResourcePersistence
->store();
515 void SfxDialogLibrary::storeResourcesAsURL
516 ( const OUString
& URL
, const OUString
& NewName
)
518 OUString
aComment(aResourceFileCommentBase
);
522 if( m_xStringResourcePersistence
.is() )
524 m_xStringResourcePersistence
->setComment( aComment
);
526 Reference
< resource::XStringResourceWithLocation
>
527 xStringResourceWithLocation( m_xStringResourcePersistence
, UNO_QUERY
);
528 if( xStringResourceWithLocation
.is() )
529 xStringResourceWithLocation
->storeAsURL( URL
);
533 void SfxDialogLibrary::storeResourcesToURL( const OUString
& URL
,
534 const Reference
< task::XInteractionHandler
>& xHandler
)
536 OUString
aComment(aResourceFileCommentBase
);
539 if( m_xStringResourcePersistence
.is() )
541 m_xStringResourcePersistence
->storeToURL
542 ( URL
, OUString(aResourceFileNameBase
), aComment
, xHandler
);
546 void SfxDialogLibrary::storeResourcesToStorage( const ::com::sun::star::uno::Reference
547 < ::com::sun::star::embed::XStorage
>& xStorage
)
549 OUString
aComment(aResourceFileCommentBase
);
552 if( m_xStringResourcePersistence
.is() )
554 m_xStringResourcePersistence
->storeToStorage
555 ( xStorage
, OUString(aResourceFileNameBase
), aComment
);
560 // XStringResourceSupplier
561 Reference
< resource::XStringResourceResolver
>
562 SAL_CALL
SfxDialogLibrary::getStringResource( ) throw (RuntimeException
, std::exception
)
564 if( !m_xStringResourcePersistence
.is() )
565 m_xStringResourcePersistence
= m_pParent
->implCreateStringResource( this );
567 Reference
< resource::XStringResourceResolver
> xRet( m_xStringResourcePersistence
, UNO_QUERY
);
571 bool SfxDialogLibrary::containsValidDialog( const ::com::sun::star::uno::Any
& aElement
)
573 Reference
< XInputStreamProvider
> xISP
;
578 bool SAL_CALL
SfxDialogLibrary::isLibraryElementValid(const css::uno::Any
& rElement
) const
580 return SfxDialogLibrary::containsValidDialog(rElement
);
585 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface
* SAL_CALL
586 com_sun_star_comp_sfx2_DialogLibraryContainer_get_implementation(::com::sun::star::uno::XComponentContext
*,
587 ::com::sun::star::uno::Sequence
<css::uno::Any
> const &)
589 return cppu::acquire(new basic::SfxDialogLibraryContainer());
593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */