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 <config_extensions.h>
21 #include <config_folders.h>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/container/XContainer.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/embed/XTransactedObject.hpp>
27 #include <com/sun/star/io/IOException.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/ucb/ContentCreationException.hpp>
31 #include <com/sun/star/xml/sax/SAXException.hpp>
32 #include <vcl/svapp.hxx>
33 #include <osl/mutex.hxx>
34 #include <vcl/errinf.hxx>
35 #include <rtl/ustring.hxx>
36 #include <sal/log.hxx>
37 #include <sot/storage.hxx>
38 #include <comphelper/getexpandeduri.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/sequence.hxx>
42 #include <namecont.hxx>
43 #include <basic/basicmanagerrepository.hxx>
44 #include <tools/diagnose_ex.h>
45 #include <tools/urlobj.hxx>
46 #include <unotools/pathoptions.hxx>
47 #include <svtools/sfxecode.hxx>
48 #include <svtools/ehdl.hxx>
49 #include <basic/basmgr.hxx>
50 #include <com/sun/star/xml/sax/Parser.hpp>
51 #include <com/sun/star/xml/sax/InputSource.hpp>
52 #include <com/sun/star/io/XOutputStream.hpp>
53 #include <com/sun/star/xml/sax/Writer.hpp>
54 #include <com/sun/star/io/XInputStream.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include <com/sun/star/uno/DeploymentException.hpp>
57 #include <com/sun/star/lang/DisposedException.hpp>
58 #include <com/sun/star/script/LibraryNotLoadedException.hpp>
59 #include <com/sun/star/script/vba/VBAScriptEventId.hpp>
60 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
61 #include <com/sun/star/util/PathSubstitution.hpp>
62 #include <com/sun/star/deployment/ExtensionManager.hpp>
63 #include <comphelper/storagehelper.hxx>
64 #include <cppuhelper/exc_hlp.hxx>
65 #include <cppuhelper/queryinterface.hxx>
66 #include <cppuhelper/supportsservice.hxx>
67 #include <cppuhelper/typeprovider.hxx>
73 using namespace com::sun::star::document
;
74 using namespace com::sun::star::container
;
75 using namespace com::sun::star::uno
;
76 using namespace com::sun::star::lang
;
77 using namespace com::sun::star::io
;
78 using namespace com::sun::star::ucb
;
79 using namespace com::sun::star::script
;
80 using namespace com::sun::star::beans
;
81 using namespace com::sun::star::xml::sax
;
82 using namespace com::sun::star::util
;
83 using namespace com::sun::star::task
;
84 using namespace com::sun::star::embed
;
85 using namespace com::sun::star::frame
;
86 using namespace com::sun::star::deployment
;
87 using namespace com::sun::star
;
91 using com::sun::star::uno::Reference
;
93 // #i34411: Flag for error handling during migration
94 static bool GbMigrationSuppressErrors
= false;
97 // Implementation class NameContainer
99 // Methods XElementAccess
100 Type
NameContainer::getElementType()
105 sal_Bool
NameContainer::hasElements()
107 bool bRet
= (mnElementCount
> 0);
111 // Methods XNameAccess
112 Any
NameContainer::getByName( const OUString
& aName
)
114 NameContainerNameMap::iterator aIt
= mHashMap
.find( aName
);
115 if( aIt
== mHashMap
.end() )
117 throw NoSuchElementException();
119 sal_Int32 iHashResult
= (*aIt
).second
;
120 Any aRetAny
= mValues
[ iHashResult
];
124 Sequence
< OUString
> NameContainer::getElementNames()
126 return comphelper::containerToSequence(mNames
);
129 sal_Bool
NameContainer::hasByName( const OUString
& aName
)
131 NameContainerNameMap::iterator aIt
= mHashMap
.find( aName
);
132 bool bRet
= ( aIt
!= mHashMap
.end() );
137 // Methods XNameReplace
138 void NameContainer::replaceByName( const OUString
& aName
, const Any
& aElement
)
140 const Type
& aAnyType
= aElement
.getValueType();
141 if( mType
!= aAnyType
)
143 throw IllegalArgumentException();
145 NameContainerNameMap::iterator aIt
= mHashMap
.find( aName
);
146 if( aIt
== mHashMap
.end() )
148 throw NoSuchElementException();
150 sal_Int32 iHashResult
= (*aIt
).second
;
151 Any aOldElement
= mValues
[ iHashResult
];
152 mValues
[ iHashResult
] = aElement
;
156 if( maContainerListeners
.getLength() > 0 )
158 ContainerEvent aEvent
;
159 aEvent
.Source
= mpxEventSource
;
160 aEvent
.Accessor
<<= aName
;
161 aEvent
.Element
= aElement
;
162 aEvent
.ReplacedElement
= aOldElement
;
163 maContainerListeners
.notifyEach( &XContainerListener::elementReplaced
, aEvent
);
166 /* After the container event has been fired (one listener will update the
167 core Basic manager), fire change event. Listeners can rely on that the
168 Basic source code of the core Basic manager is up-to-date. */
169 if( maChangesListeners
.getLength() > 0 )
172 aEvent
.Source
= mpxEventSource
;
173 aEvent
.Base
<<= aEvent
.Source
;
174 aEvent
.Changes
.realloc( 1 );
175 aEvent
.Changes
[ 0 ].Accessor
<<= aName
;
176 aEvent
.Changes
[ 0 ].Element
= aElement
;
177 aEvent
.Changes
[ 0 ].ReplacedElement
= aOldElement
;
178 maChangesListeners
.notifyEach( &XChangesListener::changesOccurred
, aEvent
);
182 void NameContainer::insertCheck(const OUString
& aName
, const Any
& aElement
)
184 NameContainerNameMap::iterator aIt
= mHashMap
.find(aName
);
185 if( aIt
!= mHashMap
.end() )
187 throw ElementExistException();
189 insertNoCheck(aName
, aElement
);
192 void NameContainer::insertNoCheck(const OUString
& aName
, const Any
& aElement
)
194 const Type
& aAnyType
= aElement
.getValueType();
195 if( mType
!= aAnyType
)
197 throw IllegalArgumentException();
200 sal_Int32 nCount
= mNames
.size();
201 mNames
.push_back( aName
);
202 mValues
.push_back( aElement
);
204 mHashMap
[ aName
] = nCount
;
208 if( maContainerListeners
.getLength() > 0 )
210 ContainerEvent aEvent
;
211 aEvent
.Source
= mpxEventSource
;
212 aEvent
.Accessor
<<= aName
;
213 aEvent
.Element
= aElement
;
214 maContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
217 /* After the container event has been fired (one listener will update the
218 core Basic manager), fire change event. Listeners can rely on that the
219 Basic source code of the core Basic manager is up-to-date. */
220 if( maChangesListeners
.getLength() > 0 )
223 aEvent
.Source
= mpxEventSource
;
224 aEvent
.Base
<<= aEvent
.Source
;
225 aEvent
.Changes
.realloc( 1 );
226 aEvent
.Changes
[ 0 ].Accessor
<<= aName
;
227 aEvent
.Changes
[ 0 ].Element
= aElement
;
228 maChangesListeners
.notifyEach( &XChangesListener::changesOccurred
, aEvent
);
232 // Methods XNameContainer
233 void NameContainer::insertByName( const OUString
& aName
, const Any
& aElement
)
235 insertCheck(aName
, aElement
);
238 void NameContainer::removeByName( const OUString
& aName
)
240 NameContainerNameMap::iterator aIt
= mHashMap
.find( aName
);
241 if( aIt
== mHashMap
.end() )
243 OUString sMessage
= "\"" + aName
+ "\" not found";
244 throw NoSuchElementException(sMessage
);
247 sal_Int32 iHashResult
= (*aIt
).second
;
248 Any aOldElement
= mValues
[ iHashResult
];
249 mHashMap
.erase( aIt
);
250 sal_Int32 iLast
= mNames
.size() - 1;
251 if( iLast
!= iHashResult
)
253 mNames
[ iHashResult
] = mNames
[ iLast
];
254 mValues
[ iHashResult
] = mValues
[ iLast
];
255 mHashMap
[ mNames
[ iHashResult
] ] = iHashResult
;
257 mNames
.resize( iLast
);
258 mValues
.resize( iLast
);
262 if( maContainerListeners
.getLength() > 0 )
264 ContainerEvent aEvent
;
265 aEvent
.Source
= mpxEventSource
;
266 aEvent
.Accessor
<<= aName
;
267 aEvent
.Element
= aOldElement
;
268 maContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
271 /* After the container event has been fired (one listener will update the
272 core Basic manager), fire change event. Listeners can rely on that the
273 Basic source code of the core Basic manager is up-to-date. */
274 if( maChangesListeners
.getLength() > 0 )
277 aEvent
.Source
= mpxEventSource
;
278 aEvent
.Base
<<= aEvent
.Source
;
279 aEvent
.Changes
.realloc( 1 );
280 aEvent
.Changes
[ 0 ].Accessor
<<= aName
;
281 // aEvent.Changes[ 0 ].Element remains empty (meaning "replaced with nothing")
282 aEvent
.Changes
[ 0 ].ReplacedElement
= aOldElement
;
283 maChangesListeners
.notifyEach( &XChangesListener::changesOccurred
, aEvent
);
288 // Methods XContainer
289 void SAL_CALL
NameContainer::addContainerListener( const Reference
< XContainerListener
>& xListener
)
291 if( !xListener
.is() )
293 throw RuntimeException("addContainerListener called with null xListener");
295 maContainerListeners
.addInterface( Reference
<XInterface
>(xListener
, UNO_QUERY
) );
298 void SAL_CALL
NameContainer::removeContainerListener( const Reference
< XContainerListener
>& xListener
)
300 if( !xListener
.is() )
302 throw RuntimeException("removeContainerListener called with null xListener");
304 maContainerListeners
.removeInterface( Reference
<XInterface
>(xListener
, UNO_QUERY
) );
307 // Methods XChangesNotifier
308 void SAL_CALL
NameContainer::addChangesListener( const Reference
< XChangesListener
>& xListener
)
310 if( !xListener
.is() )
312 throw RuntimeException("addChangesListener called with null xListener");
314 maChangesListeners
.addInterface( Reference
<XInterface
>(xListener
, UNO_QUERY
) );
317 void SAL_CALL
NameContainer::removeChangesListener( const Reference
< XChangesListener
>& xListener
)
319 if( !xListener
.is() )
321 throw RuntimeException("removeChangesListener called with null xListener");
323 maChangesListeners
.removeInterface( Reference
<XInterface
>(xListener
, UNO_QUERY
) );
329 void ModifiableHelper::setModified( bool _bModified
)
331 if ( _bModified
== mbModified
)
335 mbModified
= _bModified
;
337 if ( m_aModifyListeners
.getLength() == 0 )
341 EventObject
aModifyEvent( m_rEventSource
);
342 m_aModifyListeners
.notifyEach( &XModifyListener::modified
, aModifyEvent
);
346 VBAScriptListenerContainer::VBAScriptListenerContainer( ::osl::Mutex
& rMutex
) :
347 VBAScriptListenerContainer_BASE( rMutex
)
351 bool VBAScriptListenerContainer::implTypedNotify( const Reference
< vba::XVBAScriptListener
>& rxListener
, const vba::VBAScriptEvent
& rEvent
)
353 rxListener
->notifyVBAScriptEvent( rEvent
);
354 return true; // notify all other listeners too
358 SfxLibraryContainer::SfxLibraryContainer()
359 : SfxLibraryContainer_BASE( m_aMutex
)
360 , maVBAScriptListeners( m_aMutex
)
361 , mnRunningVBAScripts( 0 )
362 , mbVBACompat( false )
363 , maModifiable( *this, m_aMutex
)
364 , maNameContainer( new NameContainer(cppu::UnoType
<XNameAccess
>::get()) )
365 , mbOldInfoFormat( false )
366 , mbOasis2OOoFormat( false )
367 , mpBasMgr( nullptr )
368 , mbOwnBasMgr( false )
369 , meInitMode(DEFAULT
)
371 mxContext
= comphelper::getProcessComponentContext();
373 mxSFI
= ucb::SimpleFileAccess::create( mxContext
);
375 mxStringSubstitution
= util::PathSubstitution::create( mxContext
);
378 SfxLibraryContainer::~SfxLibraryContainer()
386 void SfxLibraryContainer::enterMethod()
388 Application::GetSolarMutex().acquire();
389 if ( rBHelper
.bInDispose
|| rBHelper
.bDisposed
)
391 throw DisposedException( OUString(), *this );
395 void SfxLibraryContainer::leaveMethod()
397 Application::GetSolarMutex().release();
400 BasicManager
* SfxLibraryContainer::getBasicManager()
408 Reference
< XModel
> xDocument( mxOwnerDocument
.get(), UNO_QUERY
);
410 !xDocument
.is(), "basic",
411 ("SfxLibraryContainer::getBasicManager: cannot obtain a BasicManager"
412 " without document!"));
413 if ( xDocument
.is() )
415 mpBasMgr
= BasicManagerRepository::getDocumentBasicManager( xDocument
);
418 catch (const css::ucb::ContentCreationException
&)
420 TOOLS_WARN_EXCEPTION( "basic", "SfxLibraryContainer::getBasicManager:" );
425 // Methods XStorageBasedLibraryContainer
426 Reference
< XStorage
> SAL_CALL
SfxLibraryContainer::getRootStorage()
428 LibraryContainerMethodGuard
aGuard( *this );
432 void SAL_CALL
SfxLibraryContainer::setRootStorage( const Reference
< XStorage
>& _rxRootStorage
)
434 LibraryContainerMethodGuard
aGuard( *this );
435 if ( !_rxRootStorage
.is() )
437 throw IllegalArgumentException();
439 mxStorage
= _rxRootStorage
;
443 void SAL_CALL
SfxLibraryContainer::storeLibrariesToStorage( const Reference
< XStorage
>& _rxRootStorage
)
445 LibraryContainerMethodGuard
aGuard( *this );
446 if ( !_rxRootStorage
.is() )
448 throw IllegalArgumentException();
452 storeLibraries_Impl( _rxRootStorage
, true );
454 catch( const Exception
& )
456 throw WrappedTargetException( OUString(),
457 *this, ::cppu::getCaughtException() );
462 // Methods XModifiable
463 sal_Bool
SfxLibraryContainer::isModified()
465 LibraryContainerMethodGuard
aGuard( *this );
466 if ( maModifiable
.isModified() )
470 // the library container is not modified, go through the libraries and check whether they are modified
471 Sequence
< OUString
> aNames
= maNameContainer
->getElementNames();
472 const OUString
* pNames
= aNames
.getConstArray();
473 sal_Int32 nNameCount
= aNames
.getLength();
475 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
477 OUString aName
= pNames
[ i
];
480 SfxLibrary
* pImplLib
= getImplLib( aName
);
481 if( pImplLib
->isModified() )
483 if ( aName
== "Standard" )
485 // this is a workaround that has to be implemented because
486 // empty standard library should stay marked as modified
487 // but should not be treated as modified while it is empty
488 if ( pImplLib
->hasElements() )
497 catch(const css::container::NoSuchElementException
&)
505 void SAL_CALL
SfxLibraryContainer::setModified( sal_Bool _bModified
)
507 LibraryContainerMethodGuard
aGuard( *this );
508 maModifiable
.setModified( _bModified
);
511 void SAL_CALL
SfxLibraryContainer::addModifyListener( const Reference
< XModifyListener
>& _rxListener
)
513 LibraryContainerMethodGuard
aGuard( *this );
514 maModifiable
.addModifyListener( _rxListener
);
517 void SAL_CALL
SfxLibraryContainer::removeModifyListener( const Reference
< XModifyListener
>& _rxListener
)
519 LibraryContainerMethodGuard
aGuard( *this );
520 maModifiable
.removeModifyListener( _rxListener
);
523 // Methods XPersistentLibraryContainer
524 Any SAL_CALL
SfxLibraryContainer::getRootLocation()
526 LibraryContainerMethodGuard
aGuard( *this );
527 return Any( getRootStorage() );
530 OUString SAL_CALL
SfxLibraryContainer::getContainerLocationName()
532 LibraryContainerMethodGuard
aGuard( *this );
533 return maLibrariesDir
;
536 void SAL_CALL
SfxLibraryContainer::storeLibraries( )
538 LibraryContainerMethodGuard
aGuard( *this );
541 storeLibraries_Impl( mxStorage
, mxStorage
.is() );
542 // we need to store *all* libraries if and only if we are based on a storage:
543 // in this case, storeLibraries_Impl will remove the source storage, after loading
544 // all libraries, so we need to force them to be stored, again
546 catch( const Exception
& )
548 throw WrappedTargetException( OUString(), *this, ::cppu::getCaughtException() );
552 static void checkAndCopyFileImpl( const INetURLObject
& rSourceFolderInetObj
,
553 const INetURLObject
& rTargetFolderInetObj
,
554 const OUString
& rCheckFileName
,
555 const OUString
& rCheckExtension
,
556 const Reference
< XSimpleFileAccess3
>& xSFI
)
558 INetURLObject
aTargetFolderInetObj( rTargetFolderInetObj
);
559 aTargetFolderInetObj
.insertName( rCheckFileName
, true, INetURLObject::LAST_SEGMENT
,
560 INetURLObject::EncodeMechanism::All
);
561 aTargetFolderInetObj
.setExtension( rCheckExtension
);
562 OUString aTargetFile
= aTargetFolderInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
563 if( !xSFI
->exists( aTargetFile
) )
565 INetURLObject
aSourceFolderInetObj( rSourceFolderInetObj
);
566 aSourceFolderInetObj
.insertName( rCheckFileName
, true, INetURLObject::LAST_SEGMENT
,
567 INetURLObject::EncodeMechanism::All
);
568 aSourceFolderInetObj
.setExtension( rCheckExtension
);
569 OUString aSourceFile
= aSourceFolderInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
570 xSFI
->copy( aSourceFile
, aTargetFile
);
574 static void createVariableURL( OUString
& rStr
, const OUString
& rLibName
,
575 const OUString
& rInfoFileName
, bool bUser
)
579 rStr
= "$(USER)/basic/";
583 rStr
= "$(INST)/" LIBO_SHARE_FOLDER
"/basic/";
585 rStr
+= rLibName
+ "/" + rInfoFileName
+ ".xlb/";
588 void SfxLibraryContainer::init( const OUString
& rInitialDocumentURL
, const uno::Reference
< embed::XStorage
>& rxInitialStorage
)
590 // this might be called from within the ctor, and the impl_init might (indirectly) create
591 // a UNO reference to ourself.
592 // Ensure that we're not destroyed while we're in here
593 osl_atomic_increment( &m_refCount
);
594 init_Impl( rInitialDocumentURL
, rxInitialStorage
);
595 osl_atomic_decrement( &m_refCount
);
598 void SfxLibraryContainer::init_Impl( const OUString
& rInitialDocumentURL
,
599 const uno::Reference
< embed::XStorage
>& rxInitialStorage
)
601 uno::Reference
< embed::XStorage
> xStorage
= rxInitialStorage
;
603 maInitialDocumentURL
= rInitialDocumentURL
;
604 maInfoFileName
= OUString::createFromAscii( getInfoFileName() );
605 maOldInfoFileName
= OUString::createFromAscii( getOldInfoFileName() );
606 maLibElementFileExtension
= OUString::createFromAscii( getLibElementFileExtension() );
607 maLibrariesDir
= OUString::createFromAscii( getLibrariesDir() );
609 meInitMode
= DEFAULT
;
610 INetURLObject
aInitUrlInetObj( maInitialDocumentURL
);
611 OUString aInitFileName
= aInitUrlInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
612 if( !aInitFileName
.isEmpty() )
614 // We need a BasicManager to avoid problems
615 StarBASIC
* pBas
= new StarBASIC();
616 mpBasMgr
= new BasicManager( pBas
);
619 OUString aExtension
= aInitUrlInetObj
.getExtension();
620 if( aExtension
== "xlc" )
622 meInitMode
= CONTAINER_INIT_FILE
;
623 INetURLObject
aLibPathInetObj( aInitUrlInetObj
);
624 aLibPathInetObj
.removeSegment();
625 maLibraryPath
= aLibPathInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
627 else if( aExtension
== "xlb" )
629 meInitMode
= LIBRARY_INIT_FILE
;
630 uno::Reference
< embed::XStorage
> xDummyStor
;
631 ::xmlscript::LibDescriptor aLibDesc
;
632 implLoadLibraryIndexFile( nullptr, aLibDesc
, xDummyStor
, aInitFileName
);
637 // Decide between old and new document
638 bool bOldStorage
= SotStorage::IsOLEStorage( aInitFileName
);
641 meInitMode
= OLD_BASIC_STORAGE
;
642 importFromOldStorage( aInitFileName
);
647 meInitMode
= OFFICE_DOCUMENT
;
650 xStorage
= ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName
, embed::ElementModes::READ
);
652 catch (const uno::Exception
& )
654 // TODO: error handling
662 maLibraryPath
= SvtPathOptions().GetBasicPath();
665 Reference
< XParser
> xParser
= xml::sax::Parser::create(mxContext
);
667 uno::Reference
< io::XInputStream
> xInput
;
669 mxStorage
= xStorage
;
670 bool bStorage
= mxStorage
.is();
673 // #110009: Scope to force the StorageRefs to be destructed and
674 // so the streams to be closed before the preload operation
677 uno::Reference
< embed::XStorage
> xLibrariesStor
;
681 if( !bStorage
&& meInitMode
== DEFAULT
)
685 for( int nPass
= 0 ; nPass
< nPassCount
; nPass
++ )
690 meInitMode
!= DEFAULT
&& meInitMode
!= OFFICE_DOCUMENT
, "basic",
691 "Wrong InitMode for document");
694 uno::Reference
< io::XStream
> xStream
;
695 xLibrariesStor
= xStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
697 if ( xLibrariesStor
.is() )
699 aFileName
= maInfoFileName
+ "-lc.xml";
702 xStream
= xLibrariesStor
->openStreamElement( aFileName
, embed::ElementModes::READ
);
704 catch(const uno::Exception
& )
709 mbOldInfoFormat
= true;
712 aFileName
= maOldInfoFileName
+ ".xml";
715 xStream
= xLibrariesStor
->openStreamElement( aFileName
, embed::ElementModes::READ
);
717 catch(const uno::Exception
& )
722 // Check for EA2 document version with wrong extensions
723 aFileName
= maOldInfoFileName
+ ".xli";
724 xStream
= xLibrariesStor
->openStreamElement( aFileName
, embed::ElementModes::READ
);
731 xInput
= xStream
->getInputStream();
734 catch(const uno::Exception
& )
736 // TODO: error handling?
741 std::unique_ptr
<INetURLObject
> pLibInfoInetObj
;
742 if( meInitMode
== CONTAINER_INIT_FILE
)
744 aFileName
= aInitFileName
;
750 pLibInfoInetObj
.reset(new INetURLObject( maLibraryPath
.getToken(0, ';') ));
754 pLibInfoInetObj
.reset(new INetURLObject( maLibraryPath
.getToken(1, ';') ));
756 pLibInfoInetObj
->insertName( maInfoFileName
, false, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
757 pLibInfoInetObj
->setExtension( "xlc" );
758 aFileName
= pLibInfoInetObj
->GetMainURL( INetURLObject::DecodeMechanism::NONE
);
763 xInput
= mxSFI
->openFileRead( aFileName
);
765 catch(const Exception
& )
767 // Silently tolerate empty or missing files
772 if( !xInput
.is() && nPass
== 0 )
774 INetURLObject
aLibInfoInetObj( maLibraryPath
.getToken(1, ';') );
775 aLibInfoInetObj
.insertName( maOldInfoFileName
, false, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
776 aLibInfoInetObj
.setExtension( "xli" );
777 aFileName
= aLibInfoInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
781 xInput
= mxSFI
->openFileRead( aFileName
);
782 mbOldInfoFormat
= true;
784 catch(const Exception
& )
794 source
.aInputStream
= xInput
;
795 source
.sSystemId
= aFileName
;
798 auto pLibArray
= std::make_unique
<::xmlscript::LibDescriptorArray
> ( );
802 xParser
->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray
.get() ) );
803 xParser
->parseStream( source
);
805 catch ( const xml::sax::SAXException
& )
807 TOOLS_WARN_EXCEPTION( "basic", "" );
810 catch ( const io::IOException
& )
812 TOOLS_WARN_EXCEPTION( "basic", "" );
816 sal_Int32 nLibCount
= pLibArray
->mnLibCount
;
817 for( sal_Int32 i
= 0 ; i
< nLibCount
; i
++ )
819 ::xmlscript::LibDescriptor
& rLib
= pLibArray
->mpLibs
[i
];
822 OUString aStorageURL
= rLib
.aStorageURL
;
823 if( !bStorage
&& aStorageURL
.isEmpty() && nPass
== 0 )
825 OUString aLibraryPath
;
826 if( meInitMode
== CONTAINER_INIT_FILE
)
828 aLibraryPath
= maLibraryPath
;
832 aLibraryPath
= maLibraryPath
.getToken(1, ';');
834 INetURLObject
aInetObj( aLibraryPath
);
836 aInetObj
.insertName( rLib
.aName
, true, INetURLObject::LAST_SEGMENT
,
837 INetURLObject::EncodeMechanism::All
);
838 OUString aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
839 if( mxSFI
->isFolder( aLibDirPath
) )
841 createVariableURL( rLib
.aStorageURL
, rLib
.aName
, maInfoFileName
, true );
842 maModifiable
.setModified( true );
844 else if( rLib
.bLink
)
846 // Check "share" path
847 INetURLObject
aShareInetObj( maLibraryPath
.getToken(0, ';') );
848 aShareInetObj
.insertName( rLib
.aName
, true, INetURLObject::LAST_SEGMENT
,
849 INetURLObject::EncodeMechanism::All
);
850 OUString aShareLibDirPath
= aShareInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
851 if( mxSFI
->isFolder( aShareLibDirPath
) )
853 createVariableURL( rLib
.aStorageURL
, rLib
.aName
, maInfoFileName
, false );
854 maModifiable
.setModified( true );
858 // #i25537: Ignore lib if library folder does not really exist
864 OUString aLibName
= rLib
.aName
;
866 // If the same library name is used by the shared and the
867 // user lib container index files the user file wins
868 if( nPass
== 1 && hasByName( aLibName
) )
872 SfxLibrary
* pImplLib
;
875 Reference
< XNameAccess
> xLib
=
876 createLibraryLink( aLibName
, rLib
.aStorageURL
, rLib
.bReadOnly
);
877 pImplLib
= static_cast< SfxLibrary
* >( xLib
.get() );
881 Reference
< XNameContainer
> xLib
= createLibrary( aLibName
);
882 pImplLib
= static_cast< SfxLibrary
* >( xLib
.get() );
883 pImplLib
->mbLoaded
= false;
884 pImplLib
->mbReadOnly
= rLib
.bReadOnly
;
887 checkStorageURL( rLib
.aStorageURL
, pImplLib
->maLibInfoFileURL
,
888 pImplLib
->maStorageURL
, pImplLib
->maUnexpandedStorageURL
);
891 maModifiable
.setModified( false );
893 // Read library info files
894 if( !mbOldInfoFormat
)
896 uno::Reference
< embed::XStorage
> xLibraryStor
;
897 if( !pImplLib
->mbInitialised
&& bStorage
)
901 xLibraryStor
= xLibrariesStor
->openStorageElement( rLib
.aName
,
902 embed::ElementModes::READ
);
904 catch(const uno::Exception
& )
906 #if OSL_DEBUG_LEVEL > 0
907 TOOLS_WARN_EXCEPTION(
909 "couldn't open sub storage for library \"" << rLib
.aName
<< "\"");
914 // Link is already initialised in createLibraryLink()
915 if( !pImplLib
->mbInitialised
&& (!bStorage
|| xLibraryStor
.is()) )
917 bool bLoaded
= implLoadLibraryIndexFile( pImplLib
, rLib
, xLibraryStor
, OUString() );
919 bLoaded
&& aLibName
!= rLib
.aName
, "basic",
920 ("Different library names in library container and"
921 " library info files!"));
922 if( GbMigrationSuppressErrors
&& !bLoaded
)
924 removeLibrary( aLibName
);
930 // Write new index file immediately because otherwise
931 // the library elements will be lost when storing into
932 // the new info format
933 uno::Reference
< embed::XStorage
> xTmpStorage
;
934 implStoreLibraryIndexFile( pImplLib
, rLib
, xTmpStorage
);
937 implImportLibDescriptor( pImplLib
, rLib
);
941 pImplLib
->mbSharedIndexFile
= true;
942 pImplLib
->mbReadOnly
= true;
946 // Keep flag for documents to force writing the new index files
949 mbOldInfoFormat
= false;
954 // #110009: END Scope to force the StorageRefs to be destructed
957 if( !bStorage
&& meInitMode
== DEFAULT
)
961 implScanExtensions();
963 catch(const uno::Exception
& )
965 // TODO: error handling?
966 SAL_WARN("basic", "Cannot access extensions!");
972 Sequence
< OUString
> aNames
= maNameContainer
->getElementNames();
973 const OUString
* pNames
= aNames
.getConstArray();
974 sal_Int32 nNameCount
= aNames
.getLength();
975 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
977 OUString aName
= pNames
[ i
];
978 SfxLibrary
* pImplLib
= getImplLib( aName
);
979 if( pImplLib
->mbPreload
)
981 loadLibrary( aName
);
986 if( meInitMode
!= DEFAULT
)
989 INetURLObject
aUserBasicInetObj( maLibraryPath
.getToken(1, ';') );
990 OUString
aStandardStr("Standard");
992 INetURLObject
aPrevUserBasicInetObj_1( aUserBasicInetObj
);
993 aPrevUserBasicInetObj_1
.removeSegment();
994 INetURLObject aPrevUserBasicInetObj_2
= aPrevUserBasicInetObj_1
;
995 aPrevUserBasicInetObj_1
.Append( "__basic_80" );
996 aPrevUserBasicInetObj_2
.Append( "__basic_80_2" );
999 bool bCleanUp
= false;
1002 INetURLObject aPrevUserBasicInetObj
= aPrevUserBasicInetObj_1
;
1003 OUString aPrevFolder
= aPrevUserBasicInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1004 if( mxSFI
->isFolder( aPrevFolder
) )
1006 // Check if Standard folder exists and is complete
1007 INetURLObject
aUserBasicStandardInetObj( aUserBasicInetObj
);
1008 aUserBasicStandardInetObj
.insertName( aStandardStr
, true, INetURLObject::LAST_SEGMENT
,
1009 INetURLObject::EncodeMechanism::All
);
1010 INetURLObject
aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj
);
1011 aPrevUserBasicStandardInetObj
.insertName( aStandardStr
, true, INetURLObject::LAST_SEGMENT
,
1012 INetURLObject::EncodeMechanism::All
);
1013 OUString aPrevStandardFolder
= aPrevUserBasicStandardInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1014 if( mxSFI
->isFolder( aPrevStandardFolder
) )
1016 OUString
aXlbExtension( "xlb" );
1017 OUString aCheckFileName
;
1019 // Check if script.xlb exists
1020 aCheckFileName
= "script";
1021 checkAndCopyFileImpl( aUserBasicStandardInetObj
,
1022 aPrevUserBasicStandardInetObj
,
1023 aCheckFileName
, aXlbExtension
, mxSFI
);
1025 // Check if dialog.xlb exists
1026 aCheckFileName
= "dialog";
1027 checkAndCopyFileImpl( aUserBasicStandardInetObj
,
1028 aPrevUserBasicStandardInetObj
,
1029 aCheckFileName
, aXlbExtension
, mxSFI
);
1031 // Check if module1.xba exists
1032 aCheckFileName
= "Module1";
1033 checkAndCopyFileImpl( aUserBasicStandardInetObj
,
1034 aPrevUserBasicStandardInetObj
,
1035 aCheckFileName
, "xba", mxSFI
);
1039 OUString aStandardFolder
= aUserBasicStandardInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1040 mxSFI
->copy( aStandardFolder
, aPrevStandardFolder
);
1043 OUString aPrevCopyToFolder
= aPrevUserBasicInetObj_2
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1044 mxSFI
->copy( aPrevFolder
, aPrevCopyToFolder
);
1048 aPrevUserBasicInetObj
= aPrevUserBasicInetObj_2
;
1049 aPrevFolder
= aPrevUserBasicInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1051 if( mxSFI
->isFolder( aPrevFolder
) )
1053 rtl::Reference
<SfxLibraryContainer
> pPrevCont
= createInstanceImpl();
1055 // Rename previous basic folder to make storage URLs correct during initialisation
1056 OUString aFolderUserBasic
= aUserBasicInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1057 INetURLObject
aUserBasicTmpInetObj( aUserBasicInetObj
);
1058 aUserBasicTmpInetObj
.removeSegment();
1059 aUserBasicTmpInetObj
.Append( "__basic_tmp" );
1060 OUString aFolderTmp
= aUserBasicTmpInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1062 mxSFI
->move( aFolderUserBasic
, aFolderTmp
);
1065 mxSFI
->move( aPrevFolder
, aFolderUserBasic
);
1067 catch(const Exception
& )
1069 // Move back user/basic folder
1072 mxSFI
->kill( aFolderUserBasic
);
1074 catch(const Exception
& )
1076 mxSFI
->move( aFolderTmp
, aFolderUserBasic
);
1080 INetURLObject
aPrevUserBasicLibInfoInetObj( aUserBasicInetObj
);
1081 aPrevUserBasicLibInfoInetObj
.insertName( maInfoFileName
, false, INetURLObject::LAST_SEGMENT
,
1082 INetURLObject::EncodeMechanism::All
);
1083 aPrevUserBasicLibInfoInetObj
.setExtension( "xlc");
1084 OUString aLibInfoFileName
= aPrevUserBasicLibInfoInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1085 Sequence
<Any
> aInitSeq( 1 );
1086 aInitSeq
.getArray()[0] <<= aLibInfoFileName
;
1087 GbMigrationSuppressErrors
= true;
1088 pPrevCont
->initialize( aInitSeq
);
1089 GbMigrationSuppressErrors
= false;
1091 // Rename folders back
1092 mxSFI
->move( aFolderUserBasic
, aPrevFolder
);
1093 mxSFI
->move( aFolderTmp
, aFolderUserBasic
);
1095 Sequence
< OUString
> aNames
= pPrevCont
->getElementNames();
1096 const OUString
* pNames
= aNames
.getConstArray();
1097 sal_Int32 nNameCount
= aNames
.getLength();
1099 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
1101 OUString aLibName
= pNames
[ i
];
1102 if( hasByName( aLibName
) )
1104 if( aLibName
== aStandardStr
)
1106 SfxLibrary
* pImplLib
= getImplLib( aStandardStr
);
1107 OUString aStandardFolder
= pImplLib
->maStorageURL
;
1108 mxSFI
->kill( aStandardFolder
);
1116 SfxLibrary
* pImplLib
= pPrevCont
->getImplLib( aLibName
);
1117 if( pImplLib
->mbLink
)
1119 OUString aStorageURL
= pImplLib
->maUnexpandedStorageURL
;
1120 bool bCreateLink
= true;
1121 if( aStorageURL
.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 ||
1122 aStorageURL
.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 ||
1123 aStorageURL
.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 ||
1124 aStorageURL
.indexOf( "$(INST)" ) != -1 )
1126 bCreateLink
= false;
1130 createLibraryLink( aLibName
, pImplLib
->maStorageURL
, pImplLib
->mbReadOnly
);
1135 // Move folder if not already done
1136 INetURLObject
aUserBasicLibFolderInetObj( aUserBasicInetObj
);
1137 aUserBasicLibFolderInetObj
.Append( aLibName
);
1138 OUString aLibFolder
= aUserBasicLibFolderInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1140 INetURLObject
aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj
);
1141 aPrevUserBasicLibFolderInetObj
.Append( aLibName
);
1142 OUString aPrevLibFolder
= aPrevUserBasicLibFolderInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1144 if( mxSFI
->isFolder( aPrevLibFolder
) && !mxSFI
->isFolder( aLibFolder
) )
1146 mxSFI
->move( aPrevLibFolder
, aLibFolder
);
1149 if( aLibName
== aStandardStr
)
1151 maNameContainer
->removeByName( aLibName
);
1155 Reference
< XNameContainer
> xLib
= createLibrary( aLibName
);
1156 SfxLibrary
* pNewLib
= static_cast< SfxLibrary
* >( xLib
.get() );
1157 pNewLib
->mbLoaded
= false;
1158 pNewLib
->implSetModified( false );
1159 checkStorageURL( aLibFolder
, pNewLib
->maLibInfoFileURL
,
1160 pNewLib
->maStorageURL
, pNewLib
->maUnexpandedStorageURL
);
1162 uno::Reference
< embed::XStorage
> xDummyStor
;
1163 ::xmlscript::LibDescriptor aLibDesc
;
1164 implLoadLibraryIndexFile( pNewLib
, aLibDesc
, xDummyStor
, pNewLib
->maLibInfoFileURL
);
1165 implImportLibDescriptor( pNewLib
, aLibDesc
);
1168 mxSFI
->kill( aPrevFolder
);
1171 catch(const Exception
&)
1173 TOOLS_WARN_EXCEPTION("basic", "Upgrade of Basic installation failed somehow" );
1181 INetURLObject
aPrevUserBasicInetObj_Err( aUserBasicInetObj
);
1182 aPrevUserBasicInetObj_Err
.removeSegment();
1183 aPrevUserBasicInetObj_Err
.Append( "__basic_80_err" );
1184 OUString aPrevFolder_Err
= aPrevUserBasicInetObj_Err
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1186 bool bSaved
= false;
1189 OUString aPrevFolder_1
= aPrevUserBasicInetObj_1
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1190 if( mxSFI
->isFolder( aPrevFolder_1
) )
1192 mxSFI
->move( aPrevFolder_1
, aPrevFolder_Err
);
1196 catch(const Exception
& )
1200 OUString aPrevFolder_2
= aPrevUserBasicInetObj_2
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1201 if( !bSaved
&& mxSFI
->isFolder( aPrevFolder_2
) )
1203 mxSFI
->move( aPrevFolder_2
, aPrevFolder_Err
);
1207 mxSFI
->kill( aPrevFolder_2
);
1210 catch(const Exception
& )
1214 void SfxLibraryContainer::implScanExtensions()
1216 #if HAVE_FEATURE_EXTENSIONS
1217 ScriptExtensionIterator aScriptIt
;
1219 bool bPureDialogLib
= false;
1222 OUString aLibURL
= aScriptIt
.nextBasicOrDialogLibrary( bPureDialogLib
);
1223 if (aLibURL
.isEmpty())
1225 if( bPureDialogLib
&& maInfoFileName
== "script" )
1230 sal_Int32 nLen
= aLibURL
.getLength();
1231 sal_Int32 indexLastSlash
= aLibURL
.lastIndexOf( '/' );
1232 sal_Int32 nReduceCopy
= 0;
1233 if( indexLastSlash
== nLen
- 1 )
1236 indexLastSlash
= aLibURL
.lastIndexOf( '/', nLen
- 1 );
1239 OUString aLibName
= aLibURL
.copy( indexLastSlash
+ 1, nLen
- indexLastSlash
- nReduceCopy
- 1 );
1241 // If a library of the same exists the existing library wins
1242 if( hasByName( aLibName
) )
1246 // Add index file to URL
1247 OUString aIndexFileURL
= aLibURL
;
1248 if( nReduceCopy
== 0 )
1250 aIndexFileURL
+= "/";
1252 aIndexFileURL
+= maInfoFileName
+ ".xlb";
1255 const bool bReadOnly
= false;
1256 createLibraryLink( aLibName
, aIndexFileURL
, bReadOnly
);
1263 // Handle maLibInfoFileURL and maStorageURL correctly
1264 void SfxLibraryContainer::checkStorageURL( const OUString
& aSourceURL
,
1265 OUString
& aLibInfoFileURL
, OUString
& aStorageURL
,
1266 OUString
& aUnexpandedStorageURL
)
1268 OUString aExpandedSourceURL
= expand_url( aSourceURL
);
1269 if( aExpandedSourceURL
!= aSourceURL
)
1271 aUnexpandedStorageURL
= aSourceURL
;
1273 INetURLObject
aInetObj( aExpandedSourceURL
);
1274 OUString aExtension
= aInetObj
.getExtension();
1275 if( aExtension
== "xlb" )
1278 aLibInfoFileURL
= aExpandedSourceURL
;
1279 aInetObj
.removeSegment();
1280 aStorageURL
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1284 // URL to library folder
1285 aStorageURL
= aExpandedSourceURL
;
1286 aInetObj
.insertName( maInfoFileName
, false, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
1287 aInetObj
.setExtension( "xlb" );
1288 aLibInfoFileURL
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1292 SfxLibrary
* SfxLibraryContainer::getImplLib( const OUString
& rLibraryName
)
1294 Any aLibAny
= maNameContainer
->getByName( rLibraryName
) ;
1295 Reference
< XNameAccess
> xNameAccess
;
1296 aLibAny
>>= xNameAccess
;
1297 SfxLibrary
* pImplLib
= static_cast< SfxLibrary
* >( xNameAccess
.get() );
1302 // Storing with password encryption
1304 // Empty implementation, avoids unnecessary implementation in dlgcont.cxx
1305 bool SfxLibraryContainer::implStorePasswordLibrary( SfxLibrary
*,
1307 const uno::Reference
< embed::XStorage
>&,
1308 const uno::Reference
< task::XInteractionHandler
>& )
1313 bool SfxLibraryContainer::implStorePasswordLibrary(
1314 SfxLibrary
* /*pLib*/,
1315 const OUString
& /*aName*/,
1316 const css::uno::Reference
< css::embed::XStorage
>& /*xStorage*/,
1317 const OUString
& /*aTargetURL*/,
1318 const Reference
< XSimpleFileAccess3
>& /*xToUseSFI*/,
1319 const uno::Reference
< task::XInteractionHandler
>& )
1324 bool SfxLibraryContainer::implLoadPasswordLibrary(
1325 SfxLibrary
* /*pLib*/,
1326 const OUString
& /*Name*/,
1327 bool /*bVerifyPasswordOnly*/ )
1332 OUString
SfxLibraryContainer::createAppLibraryFolder( SfxLibrary
* pLib
, const OUString
& aName
)
1334 OUString aLibDirPath
= pLib
->maStorageURL
;
1335 if( aLibDirPath
.isEmpty() )
1337 INetURLObject
aInetObj( maLibraryPath
.getToken(1, ';') );
1338 aInetObj
.insertName( aName
, true, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
1339 checkStorageURL( aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), pLib
->maLibInfoFileURL
,
1340 pLib
->maStorageURL
, pLib
->maUnexpandedStorageURL
);
1341 aLibDirPath
= pLib
->maStorageURL
;
1344 if( !mxSFI
->isFolder( aLibDirPath
) )
1348 mxSFI
->createFolder( aLibDirPath
);
1350 catch(const Exception
& )
1358 void SfxLibraryContainer::implStoreLibrary( SfxLibrary
* pLib
,
1359 const OUString
& aName
,
1360 const uno::Reference
< embed::XStorage
>& xStorage
)
1362 Reference
< XSimpleFileAccess3
> xDummySFA
;
1363 Reference
< XInteractionHandler
> xDummyHandler
;
1364 implStoreLibrary( pLib
, aName
, xStorage
, OUString(), xDummySFA
, xDummyHandler
);
1367 // New variant for library export
1368 void SfxLibraryContainer::implStoreLibrary( SfxLibrary
* pLib
,
1369 const OUString
& aName
,
1370 const uno::Reference
< embed::XStorage
>& xStorage
,
1371 const OUString
& aTargetURL
,
1372 const Reference
< XSimpleFileAccess3
>& rToUseSFI
,
1373 const Reference
< XInteractionHandler
>& xHandler
)
1375 bool bLink
= pLib
->mbLink
;
1376 bool bStorage
= xStorage
.is() && !bLink
;
1378 Sequence
< OUString
> aElementNames
= pLib
->getElementNames();
1379 sal_Int32 nNameCount
= aElementNames
.getLength();
1380 const OUString
* pNames
= aElementNames
.getConstArray();
1384 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
1386 OUString aElementName
= pNames
[ i
];
1387 OUString aStreamName
= aElementName
+ ".xml";
1389 if( !isLibraryElementValid( pLib
->getByName( aElementName
) ) )
1393 "invalid library element \"" << aElementName
<< '"');
1398 uno::Reference
< io::XStream
> xElementStream
= xStorage
->openStreamElement(
1400 embed::ElementModes::READWRITE
);
1401 // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception
1403 uno::Reference
< beans::XPropertySet
> xProps( xElementStream
, uno::UNO_QUERY
);
1405 !xProps
.is(), "basic",
1406 "The StorageStream must implement XPropertySet interface!");
1407 //if ( !xProps.is() ) //TODO
1411 xProps
->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
1413 // #87671 Allow encryption
1414 xProps
->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1416 Reference
< XOutputStream
> xOutput
= xElementStream
->getOutputStream();
1417 Reference
< XNameContainer
> xLib( pLib
);
1418 writeLibraryElement( xLib
, aElementName
, xOutput
);
1421 catch(const uno::Exception
& )
1423 SAL_WARN("basic", "Problem during storing of library!");
1424 // TODO: error handling?
1427 pLib
->storeResourcesToStorage( xStorage
);
1432 bool bExport
= !aTargetURL
.isEmpty();
1435 Reference
< XSimpleFileAccess3
> xSFI
= mxSFI
;
1436 if( rToUseSFI
.is() )
1440 OUString aLibDirPath
;
1443 INetURLObject
aInetObj( aTargetURL
);
1444 aInetObj
.insertName( aName
, true, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
1445 aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1447 if( !xSFI
->isFolder( aLibDirPath
) )
1449 xSFI
->createFolder( aLibDirPath
);
1451 pLib
->storeResourcesToURL( aLibDirPath
, xHandler
);
1455 aLibDirPath
= createAppLibraryFolder( pLib
, aName
);
1456 pLib
->storeResources();
1459 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
1461 OUString aElementName
= pNames
[ i
];
1463 INetURLObject
aElementInetObj( aLibDirPath
);
1464 aElementInetObj
.insertName( aElementName
, false,
1465 INetURLObject::LAST_SEGMENT
,
1466 INetURLObject::EncodeMechanism::All
);
1467 aElementInetObj
.setExtension( maLibElementFileExtension
);
1468 OUString
aElementPath( aElementInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1470 if( !isLibraryElementValid( pLib
->getByName( aElementName
) ) )
1474 "invalid library element \"" << aElementName
<< '"');
1478 // TODO: Check modified
1481 if( xSFI
->exists( aElementPath
) )
1483 xSFI
->kill( aElementPath
);
1485 Reference
< XOutputStream
> xOutput
= xSFI
->openFileWrite( aElementPath
);
1486 Reference
< XNameContainer
> xLib( pLib
);
1487 writeLibraryElement( xLib
, aElementName
, xOutput
);
1488 xOutput
->closeOutput();
1490 catch(const Exception
& )
1496 SfxErrorContext
aEc( ERRCTX_SFX_SAVEDOC
, aElementPath
);
1497 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
1501 catch(const Exception
& )
1511 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary
* pLib
,
1512 const ::xmlscript::LibDescriptor
& rLib
,
1513 const uno::Reference
< embed::XStorage
>& xStorage
)
1515 Reference
< XSimpleFileAccess3
> xDummySFA
;
1516 implStoreLibraryIndexFile( pLib
, rLib
, xStorage
, OUString(), xDummySFA
);
1519 // New variant for library export
1520 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary
* pLib
,
1521 const ::xmlscript::LibDescriptor
& rLib
,
1522 const uno::Reference
< embed::XStorage
>& xStorage
,
1523 const OUString
& aTargetURL
,
1524 const Reference
< XSimpleFileAccess3
>& rToUseSFI
)
1526 // Create sax writer
1527 Reference
< XWriter
> xWriter
= xml::sax::Writer::create(mxContext
);
1529 bool bLink
= pLib
->mbLink
;
1530 bool bStorage
= xStorage
.is() && !bLink
;
1533 uno::Reference
< io::XOutputStream
> xOut
;
1534 uno::Reference
< io::XStream
> xInfoStream
;
1537 OUString aStreamName
= maInfoFileName
+ "-lb.xml";
1541 xInfoStream
= xStorage
->openStreamElement( aStreamName
, embed::ElementModes::READWRITE
);
1542 SAL_WARN_IF(!xInfoStream
.is(), "basic", "No stream!");
1543 uno::Reference
< beans::XPropertySet
> xProps( xInfoStream
, uno::UNO_QUERY
);
1544 // throw uno::RuntimeException(); // TODO
1548 xProps
->setPropertyValue("MediaType", uno::Any( OUString("text/xml") ) );
1550 // #87671 Allow encryption
1551 xProps
->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1553 xOut
= xInfoStream
->getOutputStream();
1556 catch(const uno::Exception
& )
1558 SAL_WARN("basic", "Problem during storing of library index file!");
1559 // TODO: error handling?
1565 bool bExport
= !aTargetURL
.isEmpty();
1566 Reference
< XSimpleFileAccess3
> xSFI
= mxSFI
;
1567 if( rToUseSFI
.is() )
1571 OUString aLibInfoPath
;
1574 INetURLObject
aInetObj( aTargetURL
);
1575 aInetObj
.insertName( rLib
.aName
, true, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
1576 OUString aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1577 if( !xSFI
->isFolder( aLibDirPath
) )
1579 xSFI
->createFolder( aLibDirPath
);
1581 aInetObj
.insertName( maInfoFileName
, false, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
1582 aInetObj
.setExtension( "xlb" );
1583 aLibInfoPath
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1587 createAppLibraryFolder( pLib
, rLib
.aName
);
1588 aLibInfoPath
= pLib
->maLibInfoFileURL
;
1593 if( xSFI
->exists( aLibInfoPath
) )
1595 xSFI
->kill( aLibInfoPath
);
1597 xOut
= xSFI
->openFileWrite( aLibInfoPath
);
1599 catch(const Exception
& )
1605 SfxErrorContext
aEc( ERRCTX_SFX_SAVEDOC
, aLibInfoPath
);
1606 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
1611 SAL_WARN("basic", "couldn't open output stream");
1614 xWriter
->setOutputStream( xOut
);
1615 xmlscript::exportLibrary( xWriter
, rLib
);
1619 bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary
* pLib
,
1620 ::xmlscript::LibDescriptor
& rLib
,
1621 const uno::Reference
< embed::XStorage
>& xStorage
,
1622 const OUString
& aIndexFileName
)
1624 Reference
< XParser
> xParser
= xml::sax::Parser::create(mxContext
);
1626 bool bStorage
= false;
1629 bool bLink
= pLib
->mbLink
;
1630 bStorage
= xStorage
.is() && !bLink
;
1634 uno::Reference
< io::XInputStream
> xInput
;
1635 OUString aLibInfoPath
;
1638 aLibInfoPath
= maInfoFileName
+ "-lb.xml";
1642 uno::Reference
< io::XStream
> xInfoStream
=
1643 xStorage
->openStreamElement( aLibInfoPath
, embed::ElementModes::READ
);
1644 xInput
= xInfoStream
->getInputStream();
1646 catch(const uno::Exception
& )
1651 // Create Input stream
1652 //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!!
1656 createAppLibraryFolder( pLib
, rLib
.aName
);
1657 aLibInfoPath
= pLib
->maLibInfoFileURL
;
1661 aLibInfoPath
= aIndexFileName
;
1665 xInput
= mxSFI
->openFileRead( aLibInfoPath
);
1667 catch(const Exception
& )
1670 if( !GbMigrationSuppressErrors
)
1672 SfxErrorContext
aEc( ERRCTX_SFX_LOADBASIC
, aLibInfoPath
);
1673 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
1683 source
.aInputStream
= xInput
;
1684 source
.sSystemId
= aLibInfoPath
;
1689 xParser
->setDocumentHandler( ::xmlscript::importLibrary( rLib
) );
1690 xParser
->parseStream( source
);
1692 catch(const Exception
& )
1694 SAL_WARN("basic", "Parsing error");
1695 SfxErrorContext
aEc( ERRCTX_SFX_LOADBASIC
, aLibInfoPath
);
1696 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
1702 Reference
< XNameContainer
> xLib
= createLibrary( rLib
.aName
);
1703 pLib
= static_cast< SfxLibrary
* >( xLib
.get() );
1704 pLib
->mbLoaded
= false;
1705 rLib
.aStorageURL
= aIndexFileName
;
1706 checkStorageURL( rLib
.aStorageURL
, pLib
->maLibInfoFileURL
, pLib
->maStorageURL
,
1707 pLib
->maUnexpandedStorageURL
);
1709 implImportLibDescriptor( pLib
, rLib
);
1715 void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary
* pLib
,
1716 ::xmlscript::LibDescriptor
const & rLib
)
1718 if( pLib
->mbInitialised
)
1721 sal_Int32 nElementCount
= rLib
.aElementNames
.getLength();
1722 const OUString
* pElementNames
= rLib
.aElementNames
.getConstArray();
1723 Any aDummyElement
= createEmptyLibraryElement();
1724 for( sal_Int32 i
= 0 ; i
< nElementCount
; i
++ )
1726 pLib
->maNameContainer
->insertByName( pElementNames
[i
], aDummyElement
);
1728 pLib
->mbPasswordProtected
= rLib
.bPasswordProtected
;
1729 pLib
->mbReadOnly
= rLib
.bReadOnly
;
1730 pLib
->mbPreload
= rLib
.bPreload
;
1731 pLib
->implSetModified( false );
1732 pLib
->mbInitialised
= true;
1736 // Methods of new XLibraryStorage interface?
1737 void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference
< embed::XStorage
>& i_rStorage
,
1740 const Sequence
< OUString
> aNames
= maNameContainer
->getElementNames();
1741 const sal_Int32 nNameCount
= aNames
.getLength();
1742 const OUString
* pName
= aNames
.getConstArray();
1743 const OUString
* pNamesEnd
= aNames
.getConstArray() + nNameCount
;
1745 // Don't count libs from shared index file
1746 sal_Int32 nLibsToSave
= nNameCount
;
1747 for( ; pName
!= pNamesEnd
; ++pName
)
1749 SfxLibrary
* pImplLib
= getImplLib( *pName
);
1750 if( pImplLib
->mbSharedIndexFile
|| pImplLib
->mbExtension
)
1755 // Write to storage?
1756 bool bStorage
= i_rStorage
.is();
1757 uno::Reference
< embed::XStorage
> xSourceLibrariesStor
;
1758 uno::Reference
< embed::XStorage
> xTargetLibrariesStor
;
1759 OUString sTempTargetStorName
;
1760 const bool bInplaceStorage
= bStorage
&& ( i_rStorage
== mxStorage
);
1762 if( nLibsToSave
== 0 )
1764 if ( bInplaceStorage
&& mxStorage
->hasByName(maLibrariesDir
) )
1766 mxStorage
->removeElement(maLibrariesDir
);
1773 // Don't write if only empty standard lib exists
1774 if ( ( nLibsToSave
== 1 ) && ( aNames
[0] == "Standard" ) )
1776 Any aLibAny
= maNameContainer
->getByName( aNames
[0] );
1777 Reference
< XNameAccess
> xNameAccess
;
1778 aLibAny
>>= xNameAccess
;
1779 if ( ! xNameAccess
->hasElements() )
1781 if ( bInplaceStorage
&& mxStorage
->hasByName(maLibrariesDir
) )
1783 mxStorage
->removeElement(maLibrariesDir
);
1789 // create the empty target storage
1792 OUString sTargetLibrariesStoreName
;
1793 if ( bInplaceStorage
)
1795 // create a temporary target storage
1796 const OUStringBuffer aTempTargetNameBase
= maLibrariesDir
+ "_temp_";
1797 sal_Int32 index
= 0;
1800 OUStringBuffer
aTempTargetName( aTempTargetNameBase
);
1801 aTempTargetName
.append( index
++ );
1803 sTargetLibrariesStoreName
= aTempTargetName
.makeStringAndClear();
1804 if ( !i_rStorage
->hasByName( sTargetLibrariesStoreName
) )
1810 sTempTargetStorName
= sTargetLibrariesStoreName
;
1814 sTargetLibrariesStoreName
= maLibrariesDir
;
1815 if ( i_rStorage
->hasByName( sTargetLibrariesStoreName
) )
1817 i_rStorage
->removeElement( sTargetLibrariesStoreName
);
1821 xTargetLibrariesStor
.set( i_rStorage
->openStorageElement( sTargetLibrariesStoreName
, embed::ElementModes::READWRITE
), UNO_SET_THROW
);
1823 catch( const uno::Exception
& )
1825 DBG_UNHANDLED_EXCEPTION("basic");
1829 // open the source storage which might be used to copy yet-unmodified libraries
1832 if ( mxStorage
->hasByName( maLibrariesDir
) || bInplaceStorage
)
1834 xSourceLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
,
1835 bInplaceStorage
? embed::ElementModes::READWRITE
: embed::ElementModes::READ
);
1838 catch( const uno::Exception
& )
1840 DBG_UNHANDLED_EXCEPTION("basic");
1846 pName
= aNames
.getConstArray();
1847 ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs
;
1848 auto pLibArray
= std::make_unique
< ::xmlscript::LibDescriptorArray
> ( nLibsToSave
);
1849 for( ; pName
!= pNamesEnd
; ++pName
)
1851 SfxLibrary
* pImplLib
= getImplLib( *pName
);
1852 if( pImplLib
->mbSharedIndexFile
)
1856 const bool bExtensionLib
= pImplLib
->mbExtension
;
1857 ::xmlscript::LibDescriptor
& rLib
= bExtensionLib
?
1858 aLibDescriptorForExtensionLibs
: pLibArray
->mpLibs
[iArray
];
1859 if( !bExtensionLib
)
1863 rLib
.aName
= *pName
;
1865 rLib
.bLink
= pImplLib
->mbLink
;
1866 if( !bStorage
|| pImplLib
->mbLink
)
1868 rLib
.aStorageURL
= ( pImplLib
->maUnexpandedStorageURL
.getLength() ) ?
1869 pImplLib
->maUnexpandedStorageURL
: pImplLib
->maLibInfoFileURL
;
1871 rLib
.bReadOnly
= pImplLib
->mbReadOnly
;
1872 rLib
.bPreload
= pImplLib
->mbPreload
;
1873 rLib
.bPasswordProtected
= pImplLib
->mbPasswordProtected
;
1874 rLib
.aElementNames
= pImplLib
->getElementNames();
1876 if( pImplLib
->implIsModified() || bComplete
)
1878 // Testing pImplLib->implIsModified() is not reliable,
1879 // IMHO the value of pImplLib->implIsModified() should
1880 // reflect whether the library ( in-memory ) model
1881 // is in sync with the library container's own storage. Currently
1882 // whenever the library model is written to *any* storage
1883 // pImplLib->implSetModified( sal_False ) is called
1884 // The way the code works, especially the way that sfx uses
1885 // temp storage when saving ( and later sets the root storage of the
1886 // library container ) and similar madness in dbaccess means some surgery
1887 // is required to make it possible to successfully use this optimisation
1888 // It would be possible to do the implSetModified() call below only
1889 // conditionally, but that would require an additional boolean to be
1890 // passed in via the XStorageBasedDocument::storeLibrariesToStorage()...
1891 // fdo#68983: If there's a password and the password is not known, only
1892 // copying the storage works!
1893 // Can we simply copy the storage?
1894 bool isCopyStorage
= !mbOldInfoFormat
&& !mbOasis2OOoFormat
1895 && !pImplLib
->isLoadedStorable()
1896 && xSourceLibrariesStor
.is() /* null for user profile */;
1901 (void)xSourceLibrariesStor
->isStorageElement(rLib
.aName
);
1903 catch (container::NoSuchElementException
const&)
1905 isCopyStorage
= false;
1912 xSourceLibrariesStor
->copyElementTo( rLib
.aName
, xTargetLibrariesStor
, rLib
.aName
);
1914 catch( const uno::Exception
& )
1916 DBG_UNHANDLED_EXCEPTION("basic");
1917 // TODO: error handling?
1922 uno::Reference
< embed::XStorage
> xLibraryStor
;
1925 #if OSL_DEBUG_LEVEL > 0
1929 xLibraryStor
= xTargetLibrariesStor
->openStorageElement(
1931 embed::ElementModes::READWRITE
);
1932 #if OSL_DEBUG_LEVEL > 0
1934 catch(const uno::Exception
& )
1936 TOOLS_WARN_EXCEPTION(
1938 "couldn't create sub storage for library \"" << rLib
.aName
<< "\"");
1944 // Maybe lib is not loaded?!
1947 loadLibrary( rLib
.aName
);
1949 if( pImplLib
->mbPasswordProtected
)
1951 implStorePasswordLibrary( pImplLib
, rLib
.aName
, xLibraryStor
, uno::Reference
< task::XInteractionHandler
>() );
1952 // TODO: Check return value
1956 implStoreLibrary( pImplLib
, rLib
.aName
, xLibraryStor
);
1958 implStoreLibraryIndexFile( pImplLib
, rLib
, xLibraryStor
);
1963 uno::Reference
< embed::XTransactedObject
> xTransact( xLibraryStor
, uno::UNO_QUERY_THROW
);
1964 xTransact
->commit();
1966 catch(const uno::Exception
& )
1968 DBG_UNHANDLED_EXCEPTION("basic");
1969 // TODO: error handling
1974 maModifiable
.setModified( true );
1975 pImplLib
->implSetModified( false );
1978 // For container info ReadOnly refers to mbReadOnlyLink
1979 rLib
.bReadOnly
= pImplLib
->mbReadOnlyLink
;
1982 // if we did an in-place save into a storage (i.e. a save into the storage we were already based on),
1983 // then we need to clean up the temporary storage we used for this
1984 if ( bInplaceStorage
&& !sTempTargetStorName
.isEmpty() )
1987 !xSourceLibrariesStor
.is(), "basic",
1988 ("SfxLibrariesContainer::storeLibraries_impl: unexpected: we should"
1989 " have a source storage here!"));
1992 // for this, we first remove everything from the source storage, then copy the complete content
1993 // from the temporary target storage. From then on, what used to be the "source storage" becomes
1994 // the "target storage" for all subsequent operations.
1996 // (We cannot simply remove the storage, denoted by maLibrariesDir, from i_rStorage - there might be
1997 // open references to it.)
1999 if ( xSourceLibrariesStor
.is() )
2002 const Sequence
< OUString
> aRemoveNames( xSourceLibrariesStor
->getElementNames() );
2003 for ( auto const & removeName
: aRemoveNames
)
2005 xSourceLibrariesStor
->removeElement( removeName
);
2009 const Sequence
< OUString
> aCopyNames( xTargetLibrariesStor
->getElementNames() );
2010 for ( auto const & copyName
: aCopyNames
)
2012 xTargetLibrariesStor
->copyElementTo( copyName
, xSourceLibrariesStor
, copyName
);
2016 // close and remove temp target
2017 xTargetLibrariesStor
->dispose();
2018 i_rStorage
->removeElement( sTempTargetStorName
);
2019 xTargetLibrariesStor
.clear();
2020 sTempTargetStorName
.clear();
2023 xTargetLibrariesStor
= xSourceLibrariesStor
;
2024 xSourceLibrariesStor
.clear();
2026 catch( const Exception
& )
2028 DBG_UNHANDLED_EXCEPTION("basic");
2033 if( !mbOldInfoFormat
&& !maModifiable
.isModified() )
2037 maModifiable
.setModified( false );
2038 mbOldInfoFormat
= false;
2040 // Write library container info
2041 // Create sax writer
2042 Reference
< XWriter
> xWriter
= xml::sax::Writer::create(mxContext
);
2045 uno::Reference
< io::XOutputStream
> xOut
;
2046 uno::Reference
< io::XStream
> xInfoStream
;
2049 OUString aStreamName
= maInfoFileName
+ "-lc.xml";
2053 xInfoStream
= xTargetLibrariesStor
->openStreamElement( aStreamName
, embed::ElementModes::READWRITE
);
2054 uno::Reference
< beans::XPropertySet
> xProps( xInfoStream
, uno::UNO_QUERY_THROW
);
2055 xProps
->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
2057 // #87671 Allow encryption
2058 xProps
->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
2060 xOut
= xInfoStream
->getOutputStream();
2062 catch(const uno::Exception
& )
2064 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
2069 // Create Output stream
2070 INetURLObject
aLibInfoInetObj( maLibraryPath
.getToken(1, ';') );
2071 aLibInfoInetObj
.insertName( maInfoFileName
, false, INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
2072 aLibInfoInetObj
.setExtension( "xlc" );
2073 OUString
aLibInfoPath( aLibInfoInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
2077 if( mxSFI
->exists( aLibInfoPath
) )
2079 mxSFI
->kill( aLibInfoPath
);
2081 xOut
= mxSFI
->openFileWrite( aLibInfoPath
);
2083 catch(const Exception
& )
2086 SfxErrorContext
aEc( ERRCTX_SFX_SAVEDOC
, aLibInfoPath
);
2087 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
2093 SAL_WARN("basic", "couldn't open output stream");
2097 xWriter
->setOutputStream( xOut
);
2101 xmlscript::exportLibraryContainer( xWriter
, pLibArray
.get() );
2104 uno::Reference
< embed::XTransactedObject
> xTransact( xTargetLibrariesStor
, uno::UNO_QUERY_THROW
);
2105 xTransact
->commit();
2108 catch(const uno::Exception
& )
2110 SAL_WARN("basic", "Problem during storing of libraries!");
2111 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
2116 // Methods XElementAccess
2117 Type SAL_CALL
SfxLibraryContainer::getElementType()
2119 LibraryContainerMethodGuard
aGuard( *this );
2120 return maNameContainer
->getElementType();
2123 sal_Bool
SfxLibraryContainer::hasElements()
2125 LibraryContainerMethodGuard
aGuard( *this );
2126 bool bRet
= maNameContainer
->hasElements();
2130 // Methods XNameAccess
2131 Any
SfxLibraryContainer::getByName( const OUString
& aName
)
2133 LibraryContainerMethodGuard
aGuard( *this );
2134 Any aRetAny
= maNameContainer
->getByName( aName
) ;
2138 Sequence
< OUString
> SfxLibraryContainer::getElementNames()
2140 LibraryContainerMethodGuard
aGuard( *this );
2141 return maNameContainer
->getElementNames();
2144 sal_Bool
SfxLibraryContainer::hasByName( const OUString
& aName
)
2146 LibraryContainerMethodGuard
aGuard( *this );
2147 return maNameContainer
->hasByName( aName
) ;
2150 // Methods XLibraryContainer
2151 Reference
< XNameContainer
> SAL_CALL
SfxLibraryContainer::createLibrary( const OUString
& Name
)
2153 LibraryContainerMethodGuard
aGuard( *this );
2154 SfxLibrary
* pNewLib
= implCreateLibrary( Name
);
2155 pNewLib
->maLibElementFileExtension
= maLibElementFileExtension
;
2157 createVariableURL( pNewLib
->maUnexpandedStorageURL
, Name
, maInfoFileName
, true );
2159 Reference
< XNameAccess
> xNameAccess
= static_cast< XNameAccess
* >( pNewLib
);
2161 aElement
<<= xNameAccess
;
2162 maNameContainer
->insertByName( Name
, aElement
);
2163 maModifiable
.setModified( true );
2164 Reference
< XNameContainer
> xRet( xNameAccess
, UNO_QUERY
);
2168 Reference
< XNameAccess
> SAL_CALL
SfxLibraryContainer::createLibraryLink
2169 ( const OUString
& Name
, const OUString
& StorageURL
, sal_Bool ReadOnly
)
2171 LibraryContainerMethodGuard
aGuard( *this );
2172 // TODO: Check other reasons to force ReadOnly status
2177 OUString aLibInfoFileURL
;
2178 OUString aLibDirURL
;
2179 OUString aUnexpandedStorageURL
;
2180 checkStorageURL( StorageURL
, aLibInfoFileURL
, aLibDirURL
, aUnexpandedStorageURL
);
2183 SfxLibrary
* pNewLib
= implCreateLibraryLink( Name
, aLibInfoFileURL
, aLibDirURL
, ReadOnly
);
2184 pNewLib
->maLibElementFileExtension
= maLibElementFileExtension
;
2185 pNewLib
->maUnexpandedStorageURL
= aUnexpandedStorageURL
;
2186 pNewLib
->maOriginalStorageURL
= StorageURL
;
2188 uno::Reference
< embed::XStorage
> xDummyStor
;
2189 ::xmlscript::LibDescriptor aLibDesc
;
2190 implLoadLibraryIndexFile( pNewLib
, aLibDesc
, xDummyStor
, OUString() );
2191 implImportLibDescriptor( pNewLib
, aLibDesc
);
2193 Reference
< XNameAccess
> xRet
= static_cast< XNameAccess
* >( pNewLib
);
2196 maNameContainer
->insertByName( Name
, aElement
);
2197 maModifiable
.setModified( true );
2199 if( StorageURL
.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 )
2201 pNewLib
->mbExtension
= true;
2203 else if( StorageURL
.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1
2204 || StorageURL
.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 )
2206 pNewLib
->mbExtension
= true;
2207 pNewLib
->mbReadOnly
= true;
2213 void SAL_CALL
SfxLibraryContainer::removeLibrary( const OUString
& Name
)
2215 LibraryContainerMethodGuard
aGuard( *this );
2216 // Get and hold library before removing
2217 Any aLibAny
= maNameContainer
->getByName( Name
) ;
2218 Reference
< XNameAccess
> xNameAccess
;
2219 aLibAny
>>= xNameAccess
;
2220 SfxLibrary
* pImplLib
= static_cast< SfxLibrary
* >( xNameAccess
.get() );
2221 if( pImplLib
->mbReadOnly
&& !pImplLib
->mbLink
)
2223 throw IllegalArgumentException();
2225 // Remove from container
2226 maNameContainer
->removeByName( Name
);
2227 maModifiable
.setModified( true );
2229 // Delete library files, but not for linked libraries
2230 if( pImplLib
->mbLink
)
2233 if( mxStorage
.is() )
2237 if( xNameAccess
->hasElements() )
2239 Sequence
< OUString
> aNames
= pImplLib
->getElementNames();
2240 sal_Int32 nNameCount
= aNames
.getLength();
2241 const OUString
* pNames
= aNames
.getConstArray();
2242 for( sal_Int32 i
= 0 ; i
< nNameCount
; ++i
, ++pNames
)
2244 pImplLib
->removeElementWithoutChecks( *pNames
, SfxLibrary::LibraryContainerAccess() );
2248 // Delete index file
2249 createAppLibraryFolder( pImplLib
, Name
);
2250 OUString aLibInfoPath
= pImplLib
->maLibInfoFileURL
;
2253 if( mxSFI
->exists( aLibInfoPath
) )
2255 mxSFI
->kill( aLibInfoPath
);
2258 catch(const Exception
& ) {}
2260 // Delete folder if empty
2261 INetURLObject
aInetObj( maLibraryPath
.getToken(1, ';') );
2262 aInetObj
.insertName( Name
, true, INetURLObject::LAST_SEGMENT
,
2263 INetURLObject::EncodeMechanism::All
);
2264 OUString aLibDirPath
= aInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
2268 if( mxSFI
->isFolder( aLibDirPath
) )
2270 Sequence
< OUString
> aContentSeq
= mxSFI
->getFolderContents( aLibDirPath
, true );
2271 sal_Int32 nCount
= aContentSeq
.getLength();
2274 mxSFI
->kill( aLibDirPath
);
2278 catch(const Exception
& )
2283 sal_Bool SAL_CALL
SfxLibraryContainer::isLibraryLoaded( const OUString
& Name
)
2285 LibraryContainerMethodGuard
aGuard( *this );
2286 SfxLibrary
* pImplLib
= getImplLib( Name
);
2287 bool bRet
= pImplLib
->mbLoaded
;
2292 void SAL_CALL
SfxLibraryContainer::loadLibrary( const OUString
& Name
)
2294 LibraryContainerMethodGuard
aGuard( *this );
2295 Any aLibAny
= maNameContainer
->getByName( Name
) ;
2296 Reference
< XNameAccess
> xNameAccess
;
2297 aLibAny
>>= xNameAccess
;
2298 SfxLibrary
* pImplLib
= static_cast< SfxLibrary
* >( xNameAccess
.get() );
2300 bool bLoaded
= pImplLib
->mbLoaded
;
2301 pImplLib
->mbLoaded
= true;
2302 if( bLoaded
|| !xNameAccess
->hasElements() )
2305 if( pImplLib
->mbPasswordProtected
)
2307 implLoadPasswordLibrary( pImplLib
, Name
);
2311 bool bLink
= pImplLib
->mbLink
;
2312 bool bStorage
= mxStorage
.is() && !bLink
;
2314 uno::Reference
< embed::XStorage
> xLibrariesStor
;
2315 uno::Reference
< embed::XStorage
> xLibraryStor
;
2318 #if OSL_DEBUG_LEVEL > 0
2322 xLibrariesStor
= mxStorage
->openStorageElement( maLibrariesDir
, embed::ElementModes::READ
);
2324 !xLibrariesStor
.is(), "basic",
2325 ("The method must either throw exception or return a"
2327 if ( !xLibrariesStor
.is() )
2329 throw uno::RuntimeException("null returned from openStorageElement");
2332 xLibraryStor
= xLibrariesStor
->openStorageElement( Name
, embed::ElementModes::READ
);
2334 !xLibraryStor
.is(), "basic",
2335 ("The method must either throw exception or return a"
2337 if ( !xLibrariesStor
.is() )
2339 throw uno::RuntimeException("null returned from openStorageElement");
2341 #if OSL_DEBUG_LEVEL > 0
2343 catch(const uno::Exception
& )
2345 TOOLS_WARN_EXCEPTION(
2347 "couldn't open sub storage for library \"" << Name
<< "\"");
2353 Sequence
< OUString
> aNames
= pImplLib
->getElementNames();
2354 sal_Int32 nNameCount
= aNames
.getLength();
2355 const OUString
* pNames
= aNames
.getConstArray();
2356 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
2358 OUString aElementName
= pNames
[ i
];
2361 uno::Reference
< io::XInputStream
> xInStream
;
2365 uno::Reference
< io::XStream
> xElementStream
;
2367 aFile
= aElementName
+ ".xml";
2371 xElementStream
= xLibraryStor
->openStreamElement( aFile
, embed::ElementModes::READ
);
2373 catch(const uno::Exception
& )
2376 if( !xElementStream
.is() )
2378 // Check for EA2 document version with wrong extensions
2379 aFile
= aElementName
+ "." + maLibElementFileExtension
;
2382 xElementStream
= xLibraryStor
->openStreamElement( aFile
, embed::ElementModes::READ
);
2384 catch(const uno::Exception
& )
2388 if ( xElementStream
.is() )
2390 xInStream
= xElementStream
->getInputStream();
2392 if ( !xInStream
.is() )
2396 "couldn't open library element stream - attempted to"
2397 " open library \"" << Name
<< '"');
2398 throw RuntimeException("couldn't open library element stream", *this);
2403 OUString aLibDirPath
= pImplLib
->maStorageURL
;
2404 INetURLObject
aElementInetObj( aLibDirPath
);
2405 aElementInetObj
.insertName( aElementName
, false,
2406 INetURLObject::LAST_SEGMENT
,
2407 INetURLObject::EncodeMechanism::All
);
2408 aElementInetObj
.setExtension( maLibElementFileExtension
);
2409 aFile
= aElementInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
2412 Reference
< XNameContainer
> xLib( pImplLib
);
2413 Any aAny
= importLibraryElement( xLib
, aElementName
,
2415 if( pImplLib
->hasByName( aElementName
) )
2417 if( aAny
.hasValue() )
2419 pImplLib
->maNameContainer
->replaceByName( aElementName
, aAny
);
2424 pImplLib
->maNameContainer
->insertNoCheck(aElementName
, aAny
);
2427 pImplLib
->implSetModified( false );
2430 // Methods XLibraryContainer2
2431 sal_Bool SAL_CALL
SfxLibraryContainer::isLibraryLink( const OUString
& Name
)
2433 LibraryContainerMethodGuard
aGuard( *this );
2434 SfxLibrary
* pImplLib
= getImplLib( Name
);
2435 bool bRet
= pImplLib
->mbLink
;
2439 OUString SAL_CALL
SfxLibraryContainer::getLibraryLinkURL( const OUString
& Name
)
2441 LibraryContainerMethodGuard
aGuard( *this );
2442 SfxLibrary
* pImplLib
= getImplLib( Name
);
2443 bool bLink
= pImplLib
->mbLink
;
2446 throw IllegalArgumentException();
2448 OUString aRetStr
= pImplLib
->maLibInfoFileURL
;
2452 sal_Bool SAL_CALL
SfxLibraryContainer::isLibraryReadOnly( const OUString
& Name
)
2454 LibraryContainerMethodGuard
aGuard( *this );
2455 SfxLibrary
* pImplLib
= getImplLib( Name
);
2456 bool bRet
= pImplLib
->mbReadOnly
|| (pImplLib
->mbLink
&& pImplLib
->mbReadOnlyLink
);
2460 void SAL_CALL
SfxLibraryContainer::setLibraryReadOnly( const OUString
& Name
, sal_Bool bReadOnly
)
2462 LibraryContainerMethodGuard
aGuard( *this );
2463 SfxLibrary
* pImplLib
= getImplLib( Name
);
2464 if( pImplLib
->mbLink
)
2466 if( pImplLib
->mbReadOnlyLink
!= bool(bReadOnly
) )
2468 pImplLib
->mbReadOnlyLink
= bReadOnly
;
2469 pImplLib
->implSetModified( true );
2470 maModifiable
.setModified( true );
2475 if( pImplLib
->mbReadOnly
!= bool(bReadOnly
) )
2477 pImplLib
->mbReadOnly
= bReadOnly
;
2478 pImplLib
->implSetModified( true );
2483 void SAL_CALL
SfxLibraryContainer::renameLibrary( const OUString
& Name
, const OUString
& NewName
)
2485 LibraryContainerMethodGuard
aGuard( *this );
2486 if( maNameContainer
->hasByName( NewName
) )
2488 throw ElementExistException();
2490 // Get and hold library before removing
2491 Any aLibAny
= maNameContainer
->getByName( Name
) ;
2493 // #i24094 Maybe lib is not loaded!
2494 Reference
< XNameAccess
> xNameAccess
;
2495 aLibAny
>>= xNameAccess
;
2496 SfxLibrary
* pImplLib
= static_cast< SfxLibrary
* >( xNameAccess
.get() );
2497 if( pImplLib
->mbPasswordProtected
&& !pImplLib
->mbPasswordVerified
)
2499 return; // Lib with unverified password cannot be renamed
2501 loadLibrary( Name
);
2503 // Remove from container
2504 maNameContainer
->removeByName( Name
);
2505 maModifiable
.setModified( true );
2507 // Rename library folder, but not for linked libraries
2508 bool bMovedSuccessful
= true;
2511 bool bStorage
= mxStorage
.is();
2512 if( !bStorage
&& !pImplLib
->mbLink
)
2514 bMovedSuccessful
= false;
2516 OUString aLibDirPath
= pImplLib
->maStorageURL
;
2518 INetURLObject
aDestInetObj( maLibraryPath
.getToken(1, ';'));
2519 aDestInetObj
.insertName( NewName
, true, INetURLObject::LAST_SEGMENT
,
2520 INetURLObject::EncodeMechanism::All
);
2521 OUString aDestDirPath
= aDestInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
2524 OUString aLibInfoFileURL
= pImplLib
->maLibInfoFileURL
;
2525 checkStorageURL( aDestDirPath
, pImplLib
->maLibInfoFileURL
, pImplLib
->maStorageURL
,
2526 pImplLib
->maUnexpandedStorageURL
);
2530 if( mxSFI
->isFolder( aLibDirPath
) )
2532 if( !mxSFI
->isFolder( aDestDirPath
) )
2534 mxSFI
->createFolder( aDestDirPath
);
2539 if( mxSFI
->exists( pImplLib
->maLibInfoFileURL
) )
2541 mxSFI
->kill( pImplLib
->maLibInfoFileURL
);
2543 mxSFI
->move( aLibInfoFileURL
, pImplLib
->maLibInfoFileURL
);
2545 catch(const Exception
& )
2549 Sequence
< OUString
> aElementNames
= xNameAccess
->getElementNames();
2550 sal_Int32 nNameCount
= aElementNames
.getLength();
2551 const OUString
* pNames
= aElementNames
.getConstArray();
2552 for( sal_Int32 i
= 0 ; i
< nNameCount
; i
++ )
2554 OUString aElementName
= pNames
[ i
];
2556 INetURLObject
aElementInetObj( aLibDirPath
);
2557 aElementInetObj
.insertName( aElementName
, false,
2558 INetURLObject::LAST_SEGMENT
, INetURLObject::EncodeMechanism::All
);
2559 aElementInetObj
.setExtension( maLibElementFileExtension
);
2560 OUString
aElementPath( aElementInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
2562 INetURLObject
aElementDestInetObj( aDestDirPath
);
2563 aElementDestInetObj
.insertName( aElementName
, false,
2564 INetURLObject::LAST_SEGMENT
,
2565 INetURLObject::EncodeMechanism::All
);
2566 aElementDestInetObj
.setExtension( maLibElementFileExtension
);
2567 OUString
aDestElementPath( aElementDestInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
2571 if( mxSFI
->exists( aDestElementPath
) )
2573 mxSFI
->kill( aDestElementPath
);
2575 mxSFI
->move( aElementPath
, aDestElementPath
);
2577 catch(const Exception
& )
2581 pImplLib
->storeResourcesAsURL( aDestDirPath
, NewName
);
2583 // Delete folder if empty
2584 Sequence
< OUString
> aContentSeq
= mxSFI
->getFolderContents( aLibDirPath
, true );
2585 sal_Int32 nCount
= aContentSeq
.getLength();
2588 mxSFI
->kill( aLibDirPath
);
2591 bMovedSuccessful
= true;
2592 pImplLib
->implSetModified( true );
2595 catch(const Exception
& )
2597 // Restore old library
2598 maNameContainer
->insertByName( Name
, aLibAny
) ;
2602 if( bStorage
&& !pImplLib
->mbLink
)
2604 pImplLib
->implSetModified( true );
2606 if( bMovedSuccessful
)
2608 maNameContainer
->insertByName( NewName
, aLibAny
) ;
2613 // Methods XInitialization
2614 void SAL_CALL
SfxLibraryContainer::initialize( const Sequence
< Any
>& _rArguments
)
2616 LibraryContainerMethodGuard
aGuard( *this );
2617 sal_Int32 nArgCount
= _rArguments
.getLength();
2618 if ( nArgCount
== 1 )
2620 OUString sInitialDocumentURL
;
2621 Reference
< XStorageBasedDocument
> xDocument
;
2622 if ( _rArguments
[0] >>= sInitialDocumentURL
)
2624 init( sInitialDocumentURL
, nullptr );
2628 if ( _rArguments
[0] >>= xDocument
)
2630 initializeFromDocument( xDocument
);
2635 throw IllegalArgumentException();
2638 void SfxLibraryContainer::initializeFromDocument( const Reference
< XStorageBasedDocument
>& _rxDocument
)
2640 // check whether this is a valid OfficeDocument, and obtain the document's root storage
2641 Reference
< XStorage
> xDocStorage
;
2644 Reference
< XServiceInfo
> xSI( _rxDocument
, UNO_QUERY_THROW
);
2645 if ( xSI
->supportsService("com.sun.star.document.OfficeDocument"))
2647 xDocStorage
.set( _rxDocument
->getDocumentStorage(), UNO_SET_THROW
);
2649 Reference
< XModel
> xDocument( _rxDocument
, UNO_QUERY_THROW
);
2650 Reference
< XComponent
> xDocComponent( _rxDocument
, UNO_QUERY_THROW
);
2652 mxOwnerDocument
= xDocument
;
2653 startComponentListening( xDocComponent
);
2655 catch( const Exception
& ) { }
2657 if ( !xDocStorage
.is() )
2659 throw IllegalArgumentException();
2661 init( OUString(), xDocStorage
);
2664 // OEventListenerAdapter
2665 void SfxLibraryContainer::_disposing( const EventObject
& _rSource
)
2667 #if OSL_DEBUG_LEVEL > 0
2668 Reference
< XModel
> xDocument( mxOwnerDocument
.get(), UNO_QUERY
);
2670 xDocument
!= _rSource
.Source
|| !xDocument
.is(), "basic",
2671 "SfxLibraryContainer::_disposing: where does this come from?");
2679 void SAL_CALL
SfxLibraryContainer::disposing()
2681 Reference
< XModel
> xModel
= mxOwnerDocument
;
2682 EventObject
aEvent( xModel
.get() );
2683 maVBAScriptListeners
.disposing( aEvent
);
2684 stopAllComponentListening();
2685 mxOwnerDocument
.clear();
2688 // Methods XLibraryContainerPassword
2689 sal_Bool SAL_CALL
SfxLibraryContainer::isLibraryPasswordProtected( const OUString
& )
2694 sal_Bool SAL_CALL
SfxLibraryContainer::isLibraryPasswordVerified( const OUString
& )
2696 throw IllegalArgumentException();
2699 sal_Bool SAL_CALL
SfxLibraryContainer::verifyLibraryPassword( const OUString
&, const OUString
& )
2701 throw IllegalArgumentException();
2704 void SAL_CALL
SfxLibraryContainer::changeLibraryPassword(const OUString
&, const OUString
&, const OUString
& )
2706 throw IllegalArgumentException();
2709 // Methods XContainer
2710 void SAL_CALL
SfxLibraryContainer::addContainerListener( const Reference
< XContainerListener
>& xListener
)
2712 LibraryContainerMethodGuard
aGuard( *this );
2713 maNameContainer
->setEventSource( static_cast< XInterface
* >( static_cast<OWeakObject
*>(this) ) );
2714 maNameContainer
->addContainerListener( xListener
);
2717 void SAL_CALL
SfxLibraryContainer::removeContainerListener( const Reference
< XContainerListener
>& xListener
)
2719 LibraryContainerMethodGuard
aGuard( *this );
2720 maNameContainer
->removeContainerListener( xListener
);
2723 // Methods XLibraryContainerExport
2724 void SAL_CALL
SfxLibraryContainer::exportLibrary( const OUString
& Name
, const OUString
& URL
,
2725 const Reference
< XInteractionHandler
>& Handler
)
2727 LibraryContainerMethodGuard
aGuard( *this );
2728 SfxLibrary
* pImplLib
= getImplLib( Name
);
2730 Reference
< XSimpleFileAccess3
> xToUseSFI
;
2733 xToUseSFI
= ucb::SimpleFileAccess::create( mxContext
);
2734 xToUseSFI
->setInteractionHandler( Handler
);
2737 // Maybe lib is not loaded?!
2738 loadLibrary( Name
);
2740 uno::Reference
< css::embed::XStorage
> xDummyStor
;
2741 if( pImplLib
->mbPasswordProtected
)
2743 implStorePasswordLibrary( pImplLib
, Name
, xDummyStor
, URL
, xToUseSFI
, Handler
);
2747 implStoreLibrary( pImplLib
, Name
, xDummyStor
, URL
, xToUseSFI
, Handler
);
2749 ::xmlscript::LibDescriptor aLibDesc
;
2750 aLibDesc
.aName
= Name
;
2751 aLibDesc
.bLink
= false; // Link status gets lost?
2752 aLibDesc
.bReadOnly
= pImplLib
->mbReadOnly
;
2753 aLibDesc
.bPreload
= false; // Preload status gets lost?
2754 aLibDesc
.bPasswordProtected
= pImplLib
->mbPasswordProtected
;
2755 aLibDesc
.aElementNames
= pImplLib
->getElementNames();
2757 implStoreLibraryIndexFile( pImplLib
, aLibDesc
, xDummyStor
, URL
, xToUseSFI
);
2760 OUString
SfxLibraryContainer::expand_url( const OUString
& url
)
2762 if (url
.startsWithIgnoreAsciiCase( "vnd.sun.star.expand:" ))
2764 return comphelper::getExpandedUri(mxContext
, url
);
2766 else if( mxStringSubstitution
.is() )
2768 OUString
ret( mxStringSubstitution
->substituteVariables( url
, false ) );
2777 //XLibraryContainer3
2778 OUString SAL_CALL
SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString
& Name
)
2780 LibraryContainerMethodGuard
aGuard( *this );
2781 SfxLibrary
* pImplLib
= getImplLib( Name
);
2782 bool bLink
= pImplLib
->mbLink
;
2785 throw IllegalArgumentException();
2787 OUString aRetStr
= pImplLib
->maOriginalStorageURL
;
2792 // XVBACompatibility
2793 sal_Bool SAL_CALL
SfxLibraryContainer::getVBACompatibilityMode()
2798 void SAL_CALL
SfxLibraryContainer::setVBACompatibilityMode( sal_Bool _vbacompatmodeon
)
2800 /* The member variable mbVBACompat must be set first, the following call
2801 to getBasicManager() may call getVBACompatibilityMode() which returns
2803 mbVBACompat
= _vbacompatmodeon
;
2804 BasicManager
* pBasMgr
= getBasicManager();
2808 // get the standard library
2809 OUString aLibName
= pBasMgr
->GetName();
2810 if ( aLibName
.isEmpty())
2812 aLibName
= "Standard";
2814 if( StarBASIC
* pBasic
= pBasMgr
->GetLib( aLibName
) )
2816 pBasic
->SetVBAEnabled( _vbacompatmodeon
);
2818 /* If in VBA compatibility mode, force creation of the VBA Globals
2819 object. Each application will create an instance of its own
2820 implementation and store it in its Basic manager. Implementations
2821 will do all necessary additional initialization, such as
2822 registering the global "This***Doc" UNO constant, starting the
2823 document events processor etc.
2825 if( mbVBACompat
) try
2827 Reference
< XModel
> xModel( mxOwnerDocument
); // weak-ref -> ref
2828 Reference
< XMultiServiceFactory
> xFactory( xModel
, UNO_QUERY_THROW
);
2829 xFactory
->createInstance("ooo.vba.VBAGlobals");
2831 catch(const Exception
& )
2836 void SAL_CALL
SfxLibraryContainer::setProjectName( const OUString
& _projectname
)
2838 msProjectName
= _projectname
;
2839 BasicManager
* pBasMgr
= getBasicManager();
2841 // Some parts of the VBA handling ( e.g. in core basic )
2842 // code expect the name of the VBA project to be set as the name of
2843 // the basic manager. Provide fail back here.
2846 pBasMgr
->SetName( msProjectName
);
2850 sal_Int32 SAL_CALL
SfxLibraryContainer::getRunningVBAScripts()
2852 LibraryContainerMethodGuard
aGuard( *this );
2853 return mnRunningVBAScripts
;
2856 void SAL_CALL
SfxLibraryContainer::addVBAScriptListener( const Reference
< vba::XVBAScriptListener
>& rxListener
)
2858 maVBAScriptListeners
.addTypedListener( rxListener
);
2861 void SAL_CALL
SfxLibraryContainer::removeVBAScriptListener( const Reference
< vba::XVBAScriptListener
>& rxListener
)
2863 maVBAScriptListeners
.removeTypedListener( rxListener
);
2866 void SAL_CALL
SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier
, const OUString
& rModuleName
)
2868 // own lock for accessing the number of running scripts
2870 switch( nIdentifier
)
2872 case vba::VBAScriptEventId::SCRIPT_STARTED
:
2873 ++mnRunningVBAScripts
;
2875 case vba::VBAScriptEventId::SCRIPT_STOPPED
:
2876 --mnRunningVBAScripts
;
2881 Reference
< XModel
> xModel
= mxOwnerDocument
; // weak-ref -> ref
2882 vba::VBAScriptEvent
aEvent( Reference
<XInterface
>(xModel
, UNO_QUERY
), nIdentifier
, rModuleName
);
2883 maVBAScriptListeners
.notify( aEvent
);
2886 // Methods XServiceInfo
2887 sal_Bool SAL_CALL
SfxLibraryContainer::supportsService( const OUString
& _rServiceName
)
2889 return cppu::supportsService(this, _rServiceName
);
2892 // Implementation class SfxLibrary
2895 SfxLibrary::SfxLibrary( ModifiableHelper
& _rModifiable
, const Type
& aType
,
2896 const Reference
< XSimpleFileAccess3
>& xSFI
)
2897 : OComponentHelper( m_aMutex
)
2899 , mrModifiable( _rModifiable
)
2900 , maNameContainer( new NameContainer(aType
) )
2902 , mbIsModified( true )
2903 , mbInitialised( false )
2905 , mbReadOnly( false )
2906 , mbReadOnlyLink( false )
2907 , mbPreload( false )
2908 , mbPasswordProtected( false )
2909 , mbPasswordVerified( false )
2910 , mbDoc50Password( false )
2911 , mbSharedIndexFile( false )
2912 , mbExtension( false )
2916 SfxLibrary::SfxLibrary( ModifiableHelper
& _rModifiable
, const Type
& aType
,
2917 const Reference
< XSimpleFileAccess3
>& xSFI
,
2918 const OUString
& aLibInfoFileURL
, const OUString
& aStorageURL
, bool ReadOnly
)
2919 : OComponentHelper( m_aMutex
)
2921 , mrModifiable( _rModifiable
)
2922 , maNameContainer( new NameContainer(aType
) )
2924 , mbIsModified( true )
2925 , mbInitialised( false )
2926 , maLibInfoFileURL( aLibInfoFileURL
)
2927 , maStorageURL( aStorageURL
)
2929 , mbReadOnly( false )
2930 , mbReadOnlyLink( ReadOnly
)
2931 , mbPreload( false )
2932 , mbPasswordProtected( false )
2933 , mbPasswordVerified( false )
2934 , mbDoc50Password( false )
2935 , mbSharedIndexFile( false )
2936 , mbExtension( false )
2940 bool SfxLibrary::isLoadedStorable()
2942 return mbLoaded
&& (!mbPasswordProtected
|| mbPasswordVerified
);
2945 void SfxLibrary::implSetModified( bool _bIsModified
)
2947 if ( mbIsModified
== _bIsModified
)
2951 mbIsModified
= _bIsModified
;
2954 mrModifiable
.setModified( true );
2958 // Methods XInterface
2959 Any SAL_CALL
SfxLibrary::queryInterface( const Type
& rType
)
2962 ::cppu::queryInterface(
2964 static_cast< XContainer
* >( this ),
2965 static_cast< XNameContainer
* >( this ),
2966 static_cast< XNameAccess
* >( this ),
2967 static_cast< XElementAccess
* >( this ),
2968 static_cast< XChangesNotifier
* >( this ) );
2969 if( !aRet
.hasValue() )
2971 aRet
= OComponentHelper::queryInterface( rType
);
2976 // Methods XElementAccess
2977 Type
SfxLibrary::getElementType()
2979 return maNameContainer
->getElementType();
2982 sal_Bool
SfxLibrary::hasElements()
2984 bool bRet
= maNameContainer
->hasElements();
2988 // Methods XNameAccess
2989 Any
SfxLibrary::getByName( const OUString
& aName
)
2993 Any aRetAny
= maNameContainer
->getByName( aName
) ;
2997 Sequence
< OUString
> SfxLibrary::getElementNames()
2999 return maNameContainer
->getElementNames();
3002 sal_Bool
SfxLibrary::hasByName( const OUString
& aName
)
3004 bool bRet
= maNameContainer
->hasByName( aName
);
3008 void SfxLibrary::impl_checkReadOnly()
3010 if( mbReadOnly
|| (mbLink
&& mbReadOnlyLink
) )
3012 throw IllegalArgumentException(
3013 "Library is readonly.",
3020 void SfxLibrary::impl_checkLoaded()
3024 throw WrappedTargetException(
3027 Any( LibraryNotLoadedException(
3035 // Methods XNameReplace
3036 void SfxLibrary::replaceByName( const OUString
& aName
, const Any
& aElement
)
3038 impl_checkReadOnly();
3042 !isLibraryElementValid(aElement
), "basic",
3043 "SfxLibrary::replaceByName: replacing element is invalid!");
3045 maNameContainer
->replaceByName( aName
, aElement
);
3046 implSetModified( true );
3050 // Methods XNameContainer
3051 void SfxLibrary::insertByName( const OUString
& aName
, const Any
& aElement
)
3053 impl_checkReadOnly();
3057 !isLibraryElementValid(aElement
), "basic",
3058 "SfxLibrary::insertByName: to-be-inserted element is invalid!");
3060 maNameContainer
->insertByName( aName
, aElement
);
3061 implSetModified( true );
3064 void SfxLibrary::impl_removeWithoutChecks( const OUString
& _rElementName
)
3066 maNameContainer
->removeByName( _rElementName
);
3067 implSetModified( true );
3069 // Remove element file
3070 if( maStorageURL
.isEmpty() )
3073 INetURLObject
aElementInetObj( maStorageURL
);
3074 aElementInetObj
.insertName( _rElementName
, false,
3075 INetURLObject::LAST_SEGMENT
,
3076 INetURLObject::EncodeMechanism::All
);
3077 aElementInetObj
.setExtension( maLibElementFileExtension
);
3078 OUString aFile
= aElementInetObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3082 if( mxSFI
->exists( aFile
) )
3084 mxSFI
->kill( aFile
);
3087 catch(const Exception
& )
3089 DBG_UNHANDLED_EXCEPTION("basic");
3093 void SfxLibrary::removeByName( const OUString
& Name
)
3095 impl_checkReadOnly();
3097 impl_removeWithoutChecks( Name
);
3101 Sequence
< Type
> SfxLibrary::getTypes()
3103 static OTypeCollection
ourTypes_NameContainer(
3104 cppu::UnoType
<XNameContainer
>::get(),
3105 cppu::UnoType
<XContainer
>::get(),
3106 cppu::UnoType
<XChangesNotifier
>::get(),
3107 OComponentHelper::getTypes() );
3109 return ourTypes_NameContainer
.getTypes();
3113 Sequence
< sal_Int8
> SfxLibrary::getImplementationId()
3115 return css::uno::Sequence
<sal_Int8
>();
3118 // Methods XContainer
3119 void SAL_CALL
SfxLibrary::addContainerListener( const Reference
< XContainerListener
>& xListener
)
3121 maNameContainer
->setEventSource( static_cast< XInterface
* >( static_cast<OWeakObject
*>(this) ) );
3122 maNameContainer
->addContainerListener( xListener
);
3125 void SAL_CALL
SfxLibrary::removeContainerListener( const Reference
< XContainerListener
>& xListener
)
3127 maNameContainer
->removeContainerListener( xListener
);
3130 // Methods XChangesNotifier
3131 void SAL_CALL
SfxLibrary::addChangesListener( const Reference
< XChangesListener
>& xListener
)
3133 maNameContainer
->setEventSource( static_cast< XInterface
* >( static_cast<OWeakObject
*>(this) ) );
3134 maNameContainer
->addChangesListener( xListener
);
3137 void SAL_CALL
SfxLibrary::removeChangesListener( const Reference
< XChangesListener
>& xListener
)
3139 maNameContainer
->removeChangesListener( xListener
);
3143 // Implementation class ScriptExtensionIterator
3145 #define sBasicLibMediaType "application/vnd.sun.star.basic-library"
3146 #define sDialogLibMediaType "application/vnd.sun.star.dialog-library"
3148 ScriptExtensionIterator::ScriptExtensionIterator()
3149 : m_xContext( comphelper::getProcessComponentContext() )
3150 , m_eState( USER_EXTENSIONS
)
3151 , m_bUserPackagesLoaded( false )
3152 , m_bSharedPackagesLoaded( false )
3153 , m_bBundledPackagesLoaded( false )
3154 , m_iUserPackage( 0 )
3155 , m_iSharedPackage( 0 )
3156 , m_iBundledPackage( 0 )
3157 , m_pScriptSubPackageIterator( nullptr )
3160 OUString
ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib
)
3164 while( aRetLib
.isEmpty() && m_eState
!= END_REACHED
)
3168 case USER_EXTENSIONS
:
3170 Reference
< deployment::XPackage
> xScriptPackage
=
3171 implGetNextUserScriptPackage( rbPureDialogLib
);
3172 if( !xScriptPackage
.is() )
3176 aRetLib
= xScriptPackage
->getURL();
3180 case SHARED_EXTENSIONS
:
3182 Reference
< deployment::XPackage
> xScriptPackage
=
3183 implGetNextSharedScriptPackage( rbPureDialogLib
);
3184 if( !xScriptPackage
.is() )
3188 aRetLib
= xScriptPackage
->getURL();
3191 case BUNDLED_EXTENSIONS
:
3193 Reference
< deployment::XPackage
> xScriptPackage
=
3194 implGetNextBundledScriptPackage( rbPureDialogLib
);
3195 if( !xScriptPackage
.is() )
3199 aRetLib
= xScriptPackage
->getURL();
3205 ("ScriptExtensionIterator::nextBasicOrDialogLibrary():"
3206 " Invalid case END_REACHED"));
3214 ScriptSubPackageIterator::ScriptSubPackageIterator( Reference
< deployment::XPackage
> const & xMainPackage
)
3215 : m_xMainPackage( xMainPackage
)
3216 , m_bIsValid( false )
3217 , m_bIsBundle( false )
3218 , m_nSubPkgCount( 0 )
3219 , m_iNextSubPkg( 0 )
3221 if( !m_xMainPackage
.is() )
3225 // Check if parent package is registered
3226 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option( m_xMainPackage
->isRegistered
3227 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() ) );
3228 bool bRegistered
= false;
3229 if( option
.IsPresent
)
3231 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
3232 if( !reg
.IsAmbiguous
&& reg
.Value
)
3240 if( m_xMainPackage
->isBundle() )
3243 m_aSubPkgSeq
= m_xMainPackage
->getBundle( Reference
<task::XAbortChannel
>(),
3244 Reference
<ucb::XCommandEnvironment
>() );
3245 m_nSubPkgCount
= m_aSubPkgSeq
.getLength();
3250 Reference
< deployment::XPackage
> ScriptSubPackageIterator::getNextScriptSubPackage( bool& rbPureDialogLib
)
3252 rbPureDialogLib
= false;
3254 Reference
< deployment::XPackage
> xScriptPackage
;
3257 return xScriptPackage
;
3261 const Reference
< deployment::XPackage
>* pSeq
= m_aSubPkgSeq
.getConstArray();
3263 for( iPkg
= m_iNextSubPkg
; iPkg
< m_nSubPkgCount
; ++iPkg
)
3265 const Reference
< deployment::XPackage
> xSubPkg
= pSeq
[ iPkg
];
3266 xScriptPackage
= implDetectScriptPackage( xSubPkg
, rbPureDialogLib
);
3267 if( xScriptPackage
.is() )
3272 m_iNextSubPkg
= iPkg
+ 1;
3276 xScriptPackage
= implDetectScriptPackage( m_xMainPackage
, rbPureDialogLib
);
3277 m_bIsValid
= false; // No more script packages
3280 return xScriptPackage
;
3283 Reference
< deployment::XPackage
> ScriptSubPackageIterator::implDetectScriptPackage ( const Reference
< deployment::XPackage
>& rPackage
,
3284 bool& rbPureDialogLib
)
3286 Reference
< deployment::XPackage
> xScriptPackage
;
3290 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= rPackage
->getPackageType();
3291 OUString aMediaType
= xPackageTypeInfo
->getMediaType();
3292 if ( aMediaType
== sBasicLibMediaType
)
3294 xScriptPackage
= rPackage
;
3296 else if ( aMediaType
== sDialogLibMediaType
)
3298 rbPureDialogLib
= true;
3299 xScriptPackage
= rPackage
;
3303 return xScriptPackage
;
3306 Reference
< deployment::XPackage
> ScriptExtensionIterator::implGetNextUserScriptPackage( bool& rbPureDialogLib
)
3308 Reference
< deployment::XPackage
> xScriptPackage
;
3310 if( !m_bUserPackagesLoaded
)
3314 Reference
< XExtensionManager
> xManager
= ExtensionManager::get( m_xContext
);
3315 m_aUserPackagesSeq
= xManager
->getDeployedExtensions("user",
3316 Reference
< task::XAbortChannel
>(),
3317 Reference
< ucb::XCommandEnvironment
>() );
3319 catch(const css::uno::DeploymentException
& )
3321 // Special Office installations may not contain deployment code
3322 m_eState
= END_REACHED
;
3323 return xScriptPackage
;
3326 m_bUserPackagesLoaded
= true;
3329 if( m_iUserPackage
== m_aUserPackagesSeq
.getLength() )
3331 m_eState
= SHARED_EXTENSIONS
; // Later: SHARED_MODULE
3335 if( m_pScriptSubPackageIterator
== nullptr )
3337 const Reference
< deployment::XPackage
>* pUserPackages
= m_aUserPackagesSeq
.getConstArray();
3338 Reference
< deployment::XPackage
> xPackage
= pUserPackages
[ m_iUserPackage
];
3340 !xPackage
.is(), "basic",
3341 ("ScriptExtensionIterator::implGetNextUserScriptPackage():"
3342 " Invalid package"));
3343 m_pScriptSubPackageIterator
= new ScriptSubPackageIterator( xPackage
);
3346 xScriptPackage
= m_pScriptSubPackageIterator
->getNextScriptSubPackage( rbPureDialogLib
);
3347 if( !xScriptPackage
.is() )
3349 delete m_pScriptSubPackageIterator
;
3350 m_pScriptSubPackageIterator
= nullptr;
3355 return xScriptPackage
;
3358 Reference
< deployment::XPackage
> ScriptExtensionIterator::implGetNextSharedScriptPackage( bool& rbPureDialogLib
)
3360 Reference
< deployment::XPackage
> xScriptPackage
;
3362 if( !m_bSharedPackagesLoaded
)
3366 Reference
< XExtensionManager
> xSharedManager
= ExtensionManager::get( m_xContext
);
3367 m_aSharedPackagesSeq
= xSharedManager
->getDeployedExtensions("shared",
3368 Reference
< task::XAbortChannel
>(),
3369 Reference
< ucb::XCommandEnvironment
>() );
3371 catch(const css::uno::DeploymentException
& )
3373 // Special Office installations may not contain deployment code
3374 return xScriptPackage
;
3377 m_bSharedPackagesLoaded
= true;
3380 if( m_iSharedPackage
== m_aSharedPackagesSeq
.getLength() )
3382 m_eState
= BUNDLED_EXTENSIONS
;
3386 if( m_pScriptSubPackageIterator
== nullptr )
3388 const Reference
< deployment::XPackage
>* pSharedPackages
= m_aSharedPackagesSeq
.getConstArray();
3389 Reference
< deployment::XPackage
> xPackage
= pSharedPackages
[ m_iSharedPackage
];
3391 !xPackage
.is(), "basic",
3392 ("ScriptExtensionIterator::implGetNextSharedScriptPackage():"
3393 " Invalid package"));
3394 m_pScriptSubPackageIterator
= new ScriptSubPackageIterator( xPackage
);
3397 xScriptPackage
= m_pScriptSubPackageIterator
->getNextScriptSubPackage( rbPureDialogLib
);
3398 if( !xScriptPackage
.is() )
3400 delete m_pScriptSubPackageIterator
;
3401 m_pScriptSubPackageIterator
= nullptr;
3406 return xScriptPackage
;
3409 Reference
< deployment::XPackage
> ScriptExtensionIterator::implGetNextBundledScriptPackage( bool& rbPureDialogLib
)
3411 Reference
< deployment::XPackage
> xScriptPackage
;
3413 if( !m_bBundledPackagesLoaded
)
3417 Reference
< XExtensionManager
> xManager
= ExtensionManager::get( m_xContext
);
3418 m_aBundledPackagesSeq
= xManager
->getDeployedExtensions("bundled",
3419 Reference
< task::XAbortChannel
>(),
3420 Reference
< ucb::XCommandEnvironment
>() );
3422 catch(const css::uno::DeploymentException
& )
3424 // Special Office installations may not contain deployment code
3425 return xScriptPackage
;
3428 m_bBundledPackagesLoaded
= true;
3431 if( m_iBundledPackage
== m_aBundledPackagesSeq
.getLength() )
3433 m_eState
= END_REACHED
;
3437 if( m_pScriptSubPackageIterator
== nullptr )
3439 const Reference
< deployment::XPackage
>* pBundledPackages
= m_aBundledPackagesSeq
.getConstArray();
3440 Reference
< deployment::XPackage
> xPackage
= pBundledPackages
[ m_iBundledPackage
];
3442 !xPackage
.is(), "basic",
3443 ("ScriptExtensionIterator::implGetNextBundledScriptPackage():"
3444 " Invalid package"));
3445 m_pScriptSubPackageIterator
= new ScriptSubPackageIterator( xPackage
);
3448 xScriptPackage
= m_pScriptSubPackageIterator
->getNextScriptSubPackage( rbPureDialogLib
);
3449 if( !xScriptPackage
.is() )
3451 delete m_pScriptSubPackageIterator
;
3452 m_pScriptSubPackageIterator
= nullptr;
3453 m_iBundledPackage
++;
3457 return xScriptPackage
;
3460 } // namespace basic
3462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */