Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / uno / namecont.cxx
blob179df9b3d009d4351d37eedbbd164e396f2081c9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
68 #include <memory>
70 namespace basic
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;
88 using namespace cppu;
89 using namespace osl;
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()
102 return mType;
105 sal_Bool NameContainer::hasElements()
107 bool bRet = (mnElementCount > 0);
108 return bRet;
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 ];
121 return aRetAny;
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() );
133 return bRet;
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;
155 // Fire event
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 )
171 ChangesEvent aEvent;
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;
205 mnElementCount++;
207 // Fire event
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 )
222 ChangesEvent aEvent;
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 );
259 mnElementCount--;
261 // Fire event
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 )
276 ChangesEvent aEvent;
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) );
327 // ModifiableHelper
329 void ModifiableHelper::setModified( bool _bModified )
331 if ( _bModified == mbModified )
333 return;
335 mbModified = _bModified;
337 if ( m_aModifyListeners.getLength() == 0 )
339 return;
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
357 // Ctor
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()
380 if( mbOwnBasMgr )
382 delete mpBasMgr;
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()
404 if ( mpBasMgr )
406 return mpBasMgr;
408 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
409 SAL_WARN_IF(
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:" );
422 return mpBasMgr;
425 // Methods XStorageBasedLibraryContainer
426 Reference< XStorage > SAL_CALL SfxLibraryContainer::getRootStorage()
428 LibraryContainerMethodGuard aGuard( *this );
429 return mxStorage;
432 void SAL_CALL SfxLibraryContainer::setRootStorage( const Reference< XStorage >& _rxRootStorage )
434 LibraryContainerMethodGuard aGuard( *this );
435 if ( !_rxRootStorage.is() )
437 throw IllegalArgumentException();
439 mxStorage = _rxRootStorage;
440 onNewRootStorage();
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() )
468 return true;
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() )
489 return true;
491 else
493 return true;
497 catch(const css::container::NoSuchElementException&)
502 return false;
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 )
577 if( bUser )
579 rStr = "$(USER)/basic/";
581 else
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 );
617 mbOwnBasMgr = true;
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 );
633 return;
635 else
637 // Decide between old and new document
638 bool bOldStorage = SotStorage::IsOLEStorage( aInitFileName );
639 if ( bOldStorage )
641 meInitMode = OLD_BASIC_STORAGE;
642 importFromOldStorage( aInitFileName );
643 return;
645 else
647 meInitMode = OFFICE_DOCUMENT;
650 xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( aInitFileName, embed::ElementModes::READ );
652 catch (const uno::Exception& )
654 // TODO: error handling
659 else
661 // Default paths
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;
678 OUString aFileName;
680 int nPassCount = 1;
681 if( !bStorage && meInitMode == DEFAULT )
683 nPassCount = 2;
685 for( int nPass = 0 ; nPass < nPassCount ; nPass++ )
687 if( bStorage )
689 SAL_WARN_IF(
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& )
707 if( !xStream.is() )
709 mbOldInfoFormat = true;
711 // Check old version
712 aFileName = maOldInfoFileName + ".xml";
715 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
717 catch(const uno::Exception& )
720 if( !xStream.is() )
722 // Check for EA2 document version with wrong extensions
723 aFileName = maOldInfoFileName + ".xli";
724 xStream = xLibrariesStor->openStreamElement( aFileName, embed::ElementModes::READ );
729 if ( xStream.is() )
731 xInput = xStream->getInputStream();
734 catch(const uno::Exception& )
736 // TODO: error handling?
739 else
741 std::unique_ptr<INetURLObject> pLibInfoInetObj;
742 if( meInitMode == CONTAINER_INIT_FILE )
744 aFileName = aInitFileName;
746 else
748 if( nPass == 1 )
750 pLibInfoInetObj.reset(new INetURLObject( maLibraryPath.getToken(0, ';') ));
752 else
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
768 xInput.clear();
771 // Old variant?
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& )
786 xInput.clear();
791 if( xInput.is() )
793 InputSource source;
794 source.aInputStream = xInput;
795 source.sSystemId = aFileName;
797 // start parsing
798 std::unique_ptr< ::xmlscript::LibDescriptorArray> pLibArray(new ::xmlscript::LibDescriptorArray());
802 xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( pLibArray.get() ) );
803 xParser->parseStream( source );
805 catch ( const xml::sax::SAXException& )
807 TOOLS_WARN_EXCEPTION( "basic", "" );
808 return;
810 catch ( const io::IOException& )
812 TOOLS_WARN_EXCEPTION( "basic", "" );
813 return;
816 sal_Int32 nLibCount = pLibArray->mnLibCount;
817 for( sal_Int32 i = 0 ; i < nLibCount ; i++ )
819 ::xmlscript::LibDescriptor& rLib = pLibArray->mpLibs[i];
821 // Check storage URL
822 OUString aStorageURL = rLib.aStorageURL;
823 if( !bStorage && aStorageURL.isEmpty() && nPass == 0 )
825 OUString aLibraryPath;
826 if( meInitMode == CONTAINER_INIT_FILE )
828 aLibraryPath = maLibraryPath;
830 else
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 );
856 else
858 // #i25537: Ignore lib if library folder does not really exist
859 continue;
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 ) )
870 continue;
872 SfxLibrary* pImplLib;
873 if( rLib.bLink )
875 Reference< XNameAccess > xLib =
876 createLibraryLink( aLibName, rLib.aStorageURL, rLib.bReadOnly );
877 pImplLib = static_cast< SfxLibrary* >( xLib.get() );
879 else
881 Reference< XNameContainer > xLib = createLibrary( aLibName );
882 pImplLib = static_cast< SfxLibrary* >( xLib.get() );
883 pImplLib->mbLoaded = false;
884 pImplLib->mbReadOnly = rLib.bReadOnly;
885 if( !bStorage )
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(
908 "basic",
909 "couldn't open sub storage for library \"" << rLib.aName << "\"");
910 #endif
914 // Link is already initialised in createLibraryLink()
915 if( !pImplLib->mbInitialised && (!bStorage || xLibraryStor.is()) )
917 bool bLoaded = implLoadLibraryIndexFile( pImplLib, rLib, xLibraryStor, OUString() );
918 SAL_WARN_IF(
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 );
928 else if( !bStorage )
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 );
939 if( nPass == 1 )
941 pImplLib->mbSharedIndexFile = true;
942 pImplLib->mbReadOnly = true;
946 // Keep flag for documents to force writing the new index files
947 if( !bStorage )
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!");
970 // Preload?
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 )
988 INetURLObject aUserBasicInetObj( maLibraryPath.getToken(1, ';') );
989 OUString aStandardStr("Standard");
991 INetURLObject aPrevUserBasicInetObj_1( aUserBasicInetObj );
992 aPrevUserBasicInetObj_1.removeSegment();
993 INetURLObject aPrevUserBasicInetObj_2 = aPrevUserBasicInetObj_1;
994 aPrevUserBasicInetObj_1.Append( "__basic_80" );
995 aPrevUserBasicInetObj_2.Append( "__basic_80_2" );
997 // #i93163
998 bool bCleanUp = false;
1001 INetURLObject aPrevUserBasicInetObj = aPrevUserBasicInetObj_1;
1002 OUString aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1003 if( mxSFI->isFolder( aPrevFolder ) )
1005 // Check if Standard folder exists and is complete
1006 INetURLObject aUserBasicStandardInetObj( aUserBasicInetObj );
1007 aUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
1008 INetURLObject::EncodeMechanism::All );
1009 INetURLObject aPrevUserBasicStandardInetObj( aPrevUserBasicInetObj );
1010 aPrevUserBasicStandardInetObj.insertName( aStandardStr, true, INetURLObject::LAST_SEGMENT,
1011 INetURLObject::EncodeMechanism::All );
1012 OUString aPrevStandardFolder = aPrevUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1013 if( mxSFI->isFolder( aPrevStandardFolder ) )
1015 OUString aXlbExtension( "xlb" );
1016 OUString aCheckFileName;
1018 // Check if script.xlb exists
1019 aCheckFileName = "script";
1020 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1021 aPrevUserBasicStandardInetObj,
1022 aCheckFileName, aXlbExtension, mxSFI );
1024 // Check if dialog.xlb exists
1025 aCheckFileName = "dialog";
1026 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1027 aPrevUserBasicStandardInetObj,
1028 aCheckFileName, aXlbExtension, mxSFI );
1030 // Check if module1.xba exists
1031 aCheckFileName = "Module1";
1032 checkAndCopyFileImpl( aUserBasicStandardInetObj,
1033 aPrevUserBasicStandardInetObj,
1034 aCheckFileName, "xba", mxSFI );
1036 else
1038 OUString aStandardFolder = aUserBasicStandardInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1039 mxSFI->copy( aStandardFolder, aPrevStandardFolder );
1042 OUString aPrevCopyToFolder = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1043 mxSFI->copy( aPrevFolder, aPrevCopyToFolder );
1045 else
1047 aPrevUserBasicInetObj = aPrevUserBasicInetObj_2;
1048 aPrevFolder = aPrevUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1050 if( mxSFI->isFolder( aPrevFolder ) )
1052 rtl::Reference<SfxLibraryContainer> pPrevCont = createInstanceImpl();
1054 // Rename previous basic folder to make storage URLs correct during initialisation
1055 OUString aFolderUserBasic = aUserBasicInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1056 INetURLObject aUserBasicTmpInetObj( aUserBasicInetObj );
1057 aUserBasicTmpInetObj.removeSegment();
1058 aUserBasicTmpInetObj.Append( "__basic_tmp" );
1059 OUString aFolderTmp = aUserBasicTmpInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1061 mxSFI->move( aFolderUserBasic, aFolderTmp );
1064 mxSFI->move( aPrevFolder, aFolderUserBasic );
1066 catch(const Exception& )
1068 // Move back user/basic folder
1071 mxSFI->kill( aFolderUserBasic );
1073 catch(const Exception& )
1075 mxSFI->move( aFolderTmp, aFolderUserBasic );
1076 throw;
1079 INetURLObject aPrevUserBasicLibInfoInetObj( aUserBasicInetObj );
1080 aPrevUserBasicLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT,
1081 INetURLObject::EncodeMechanism::All );
1082 aPrevUserBasicLibInfoInetObj.setExtension( "xlc");
1083 OUString aLibInfoFileName = aPrevUserBasicLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1084 Sequence<Any> aInitSeq( 1 );
1085 aInitSeq.getArray()[0] <<= aLibInfoFileName;
1086 GbMigrationSuppressErrors = true;
1087 pPrevCont->initialize( aInitSeq );
1088 GbMigrationSuppressErrors = false;
1090 // Rename folders back
1091 mxSFI->move( aFolderUserBasic, aPrevFolder );
1092 mxSFI->move( aFolderTmp, aFolderUserBasic );
1094 Sequence< OUString > aNames = pPrevCont->getElementNames();
1095 const OUString* pNames = aNames.getConstArray();
1096 sal_Int32 nNameCount = aNames.getLength();
1098 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1100 OUString aLibName = pNames[ i ];
1101 if( hasByName( aLibName ) )
1103 if( aLibName == aStandardStr )
1105 SfxLibrary* pImplLib = getImplLib( aStandardStr );
1106 OUString aStandardFolder = pImplLib->maStorageURL;
1107 mxSFI->kill( aStandardFolder );
1109 else
1111 continue;
1115 SfxLibrary* pImplLib = pPrevCont->getImplLib( aLibName );
1116 if( pImplLib->mbLink )
1118 OUString aStorageURL = pImplLib->maUnexpandedStorageURL;
1119 bool bCreateLink = true;
1120 if( aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 ||
1121 aStorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1 ||
1122 aStorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 ||
1123 aStorageURL.indexOf( "$(INST)" ) != -1 )
1125 bCreateLink = false;
1127 if( bCreateLink )
1129 createLibraryLink( aLibName, pImplLib->maStorageURL, pImplLib->mbReadOnly );
1132 else
1134 // Move folder if not already done
1135 INetURLObject aUserBasicLibFolderInetObj( aUserBasicInetObj );
1136 aUserBasicLibFolderInetObj.Append( aLibName );
1137 OUString aLibFolder = aUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1139 INetURLObject aPrevUserBasicLibFolderInetObj( aPrevUserBasicInetObj );
1140 aPrevUserBasicLibFolderInetObj.Append( aLibName );
1141 OUString aPrevLibFolder = aPrevUserBasicLibFolderInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1143 if( mxSFI->isFolder( aPrevLibFolder ) && !mxSFI->isFolder( aLibFolder ) )
1145 mxSFI->move( aPrevLibFolder, aLibFolder );
1148 if( aLibName == aStandardStr )
1150 maNameContainer->removeByName( aLibName );
1153 // Create library
1154 Reference< XNameContainer > xLib = createLibrary( aLibName );
1155 SfxLibrary* pNewLib = static_cast< SfxLibrary* >( xLib.get() );
1156 pNewLib->mbLoaded = false;
1157 pNewLib->implSetModified( false );
1158 checkStorageURL( aLibFolder, pNewLib->maLibInfoFileURL,
1159 pNewLib->maStorageURL, pNewLib->maUnexpandedStorageURL );
1161 uno::Reference< embed::XStorage > xDummyStor;
1162 ::xmlscript::LibDescriptor aLibDesc;
1163 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, pNewLib->maLibInfoFileURL );
1164 implImportLibDescriptor( pNewLib, aLibDesc );
1167 mxSFI->kill( aPrevFolder );
1170 catch(const Exception&)
1172 TOOLS_WARN_EXCEPTION("basic", "Upgrade of Basic installation failed somehow" );
1173 bCleanUp = true;
1176 // #i93163
1177 if( bCleanUp )
1179 INetURLObject aPrevUserBasicInetObj_Err( aUserBasicInetObj );
1180 aPrevUserBasicInetObj_Err.removeSegment();
1181 aPrevUserBasicInetObj_Err.Append( "__basic_80_err" );
1182 OUString aPrevFolder_Err = aPrevUserBasicInetObj_Err.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1184 bool bSaved = false;
1187 OUString aPrevFolder_1 = aPrevUserBasicInetObj_1.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1188 if( mxSFI->isFolder( aPrevFolder_1 ) )
1190 mxSFI->move( aPrevFolder_1, aPrevFolder_Err );
1191 bSaved = true;
1194 catch(const Exception& )
1198 OUString aPrevFolder_2 = aPrevUserBasicInetObj_2.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1199 if( !bSaved && mxSFI->isFolder( aPrevFolder_2 ) )
1201 mxSFI->move( aPrevFolder_2, aPrevFolder_Err );
1203 else
1205 mxSFI->kill( aPrevFolder_2 );
1208 catch(const Exception& )
1214 void SfxLibraryContainer::implScanExtensions()
1216 #if HAVE_FEATURE_EXTENSIONS
1217 ScriptExtensionIterator aScriptIt;
1218 OUString aLibURL;
1220 bool bPureDialogLib = false;
1221 while ( !(aLibURL = aScriptIt.nextBasicOrDialogLibrary( bPureDialogLib )).isEmpty())
1223 if( bPureDialogLib && maInfoFileName == "script" )
1225 continue;
1227 // Extract lib name
1228 sal_Int32 nLen = aLibURL.getLength();
1229 sal_Int32 indexLastSlash = aLibURL.lastIndexOf( '/' );
1230 sal_Int32 nReduceCopy = 0;
1231 if( indexLastSlash == nLen - 1 )
1233 nReduceCopy = 1;
1234 indexLastSlash = aLibURL.lastIndexOf( '/', nLen - 1 );
1237 OUString aLibName = aLibURL.copy( indexLastSlash + 1, nLen - indexLastSlash - nReduceCopy - 1 );
1239 // If a library of the same exists the existing library wins
1240 if( hasByName( aLibName ) )
1242 continue;
1244 // Add index file to URL
1245 OUString aIndexFileURL = aLibURL;
1246 if( nReduceCopy == 0 )
1248 aIndexFileURL += "/";
1250 aIndexFileURL += maInfoFileName + ".xlb";
1252 // Create link
1253 const bool bReadOnly = false;
1254 createLibraryLink( aLibName, aIndexFileURL, bReadOnly );
1256 #else
1257 (void) this;
1258 #endif
1261 // Handle maLibInfoFileURL and maStorageURL correctly
1262 void SfxLibraryContainer::checkStorageURL( const OUString& aSourceURL,
1263 OUString& aLibInfoFileURL, OUString& aStorageURL,
1264 OUString& aUnexpandedStorageURL )
1266 OUString aExpandedSourceURL = expand_url( aSourceURL );
1267 if( aExpandedSourceURL != aSourceURL )
1269 aUnexpandedStorageURL = aSourceURL;
1271 INetURLObject aInetObj( aExpandedSourceURL );
1272 OUString aExtension = aInetObj.getExtension();
1273 if( aExtension == "xlb" )
1275 // URL to xlb file
1276 aLibInfoFileURL = aExpandedSourceURL;
1277 aInetObj.removeSegment();
1278 aStorageURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1280 else
1282 // URL to library folder
1283 aStorageURL = aExpandedSourceURL;
1284 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1285 aInetObj.setExtension( "xlb" );
1286 aLibInfoFileURL = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1290 SfxLibrary* SfxLibraryContainer::getImplLib( const OUString& rLibraryName )
1292 Any aLibAny = maNameContainer->getByName( rLibraryName ) ;
1293 Reference< XNameAccess > xNameAccess;
1294 aLibAny >>= xNameAccess;
1295 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
1296 return pImplLib;
1300 // Storing with password encryption
1302 // Empty implementation, avoids unnecessary implementation in dlgcont.cxx
1303 bool SfxLibraryContainer::implStorePasswordLibrary( SfxLibrary*,
1304 const OUString&,
1305 const uno::Reference< embed::XStorage >&,
1306 const uno::Reference< task::XInteractionHandler >& )
1308 return false;
1311 bool SfxLibraryContainer::implStorePasswordLibrary(
1312 SfxLibrary* /*pLib*/,
1313 const OUString& /*aName*/,
1314 const css::uno::Reference< css::embed::XStorage >& /*xStorage*/,
1315 const OUString& /*aTargetURL*/,
1316 const Reference< XSimpleFileAccess3 >& /*xToUseSFI*/,
1317 const uno::Reference< task::XInteractionHandler >& )
1319 return false;
1322 bool SfxLibraryContainer::implLoadPasswordLibrary(
1323 SfxLibrary* /*pLib*/,
1324 const OUString& /*Name*/,
1325 bool /*bVerifyPasswordOnly*/ )
1327 return true;
1330 OUString SfxLibraryContainer::createAppLibraryFolder( SfxLibrary* pLib, const OUString& aName )
1332 OUString aLibDirPath = pLib->maStorageURL;
1333 if( aLibDirPath.isEmpty() )
1335 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') );
1336 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1337 checkStorageURL( aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), pLib->maLibInfoFileURL,
1338 pLib->maStorageURL, pLib->maUnexpandedStorageURL );
1339 aLibDirPath = pLib->maStorageURL;
1342 if( !mxSFI->isFolder( aLibDirPath ) )
1346 mxSFI->createFolder( aLibDirPath );
1348 catch(const Exception& )
1352 return aLibDirPath;
1355 // Storing
1356 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
1357 const OUString& aName,
1358 const uno::Reference< embed::XStorage >& xStorage )
1360 Reference< XSimpleFileAccess3 > xDummySFA;
1361 Reference< XInteractionHandler > xDummyHandler;
1362 implStoreLibrary( pLib, aName, xStorage, OUString(), xDummySFA, xDummyHandler );
1365 // New variant for library export
1366 void SfxLibraryContainer::implStoreLibrary( SfxLibrary* pLib,
1367 const OUString& aName,
1368 const uno::Reference< embed::XStorage >& xStorage,
1369 const OUString& aTargetURL,
1370 const Reference< XSimpleFileAccess3 >& rToUseSFI,
1371 const Reference< XInteractionHandler >& xHandler )
1373 bool bLink = pLib->mbLink;
1374 bool bStorage = xStorage.is() && !bLink;
1376 Sequence< OUString > aElementNames = pLib->getElementNames();
1377 sal_Int32 nNameCount = aElementNames.getLength();
1378 const OUString* pNames = aElementNames.getConstArray();
1380 if( bStorage )
1382 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1384 OUString aElementName = pNames[ i ];
1385 OUString aStreamName = aElementName + ".xml";
1387 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
1389 SAL_WARN(
1390 "basic",
1391 "invalid library element \"" << aElementName << '"');
1392 continue;
1396 uno::Reference< io::XStream > xElementStream = xStorage->openStreamElement(
1397 aStreamName,
1398 embed::ElementModes::READWRITE );
1399 // throw uno::RuntimeException(); // TODO: method must either return the stream or throw an exception
1401 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
1402 SAL_WARN_IF(
1403 !xProps.is(), "basic",
1404 "The StorageStream must implement XPropertySet interface!");
1405 //if ( !xProps.is() ) //TODO
1407 if ( xProps.is() )
1409 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
1411 // #87671 Allow encryption
1412 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1414 Reference< XOutputStream > xOutput = xElementStream->getOutputStream();
1415 Reference< XNameContainer > xLib( pLib );
1416 writeLibraryElement( xLib, aElementName, xOutput );
1419 catch(const uno::Exception& )
1421 SAL_WARN("basic", "Problem during storing of library!");
1422 // TODO: error handling?
1425 pLib->storeResourcesToStorage( xStorage );
1427 else
1429 // Export?
1430 bool bExport = !aTargetURL.isEmpty();
1433 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
1434 if( rToUseSFI.is() )
1436 xSFI = rToUseSFI;
1438 OUString aLibDirPath;
1439 if( bExport )
1441 INetURLObject aInetObj( aTargetURL );
1442 aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1443 aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1445 if( !xSFI->isFolder( aLibDirPath ) )
1447 xSFI->createFolder( aLibDirPath );
1449 pLib->storeResourcesToURL( aLibDirPath, xHandler );
1451 else
1453 aLibDirPath = createAppLibraryFolder( pLib, aName );
1454 pLib->storeResources();
1457 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
1459 OUString aElementName = pNames[ i ];
1461 INetURLObject aElementInetObj( aLibDirPath );
1462 aElementInetObj.insertName( aElementName, false,
1463 INetURLObject::LAST_SEGMENT,
1464 INetURLObject::EncodeMechanism::All );
1465 aElementInetObj.setExtension( maLibElementFileExtension );
1466 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1468 if( !isLibraryElementValid( pLib->getByName( aElementName ) ) )
1470 SAL_WARN(
1471 "basic",
1472 "invalid library element \"" << aElementName << '"');
1473 continue;
1476 // TODO: Check modified
1479 if( xSFI->exists( aElementPath ) )
1481 xSFI->kill( aElementPath );
1483 Reference< XOutputStream > xOutput = xSFI->openFileWrite( aElementPath );
1484 Reference< XNameContainer > xLib( pLib );
1485 writeLibraryElement( xLib, aElementName, xOutput );
1486 xOutput->closeOutput();
1488 catch(const Exception& )
1490 if( bExport )
1492 throw;
1494 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aElementPath );
1495 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1499 catch(const Exception& )
1501 if( bExport )
1503 throw;
1509 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
1510 const ::xmlscript::LibDescriptor& rLib,
1511 const uno::Reference< embed::XStorage >& xStorage )
1513 Reference< XSimpleFileAccess3 > xDummySFA;
1514 implStoreLibraryIndexFile( pLib, rLib, xStorage, OUString(), xDummySFA );
1517 // New variant for library export
1518 void SfxLibraryContainer::implStoreLibraryIndexFile( SfxLibrary* pLib,
1519 const ::xmlscript::LibDescriptor& rLib,
1520 const uno::Reference< embed::XStorage >& xStorage,
1521 const OUString& aTargetURL,
1522 const Reference< XSimpleFileAccess3 >& rToUseSFI )
1524 // Create sax writer
1525 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
1527 bool bLink = pLib->mbLink;
1528 bool bStorage = xStorage.is() && !bLink;
1530 // Write info file
1531 uno::Reference< io::XOutputStream > xOut;
1532 uno::Reference< io::XStream > xInfoStream;
1533 if( bStorage )
1535 OUString aStreamName = maInfoFileName + "-lb.xml";
1539 xInfoStream = xStorage->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
1540 SAL_WARN_IF(!xInfoStream.is(), "basic", "No stream!");
1541 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY );
1542 // throw uno::RuntimeException(); // TODO
1544 if ( xProps.is() )
1546 xProps->setPropertyValue("MediaType", uno::Any( OUString("text/xml") ) );
1548 // #87671 Allow encryption
1549 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
1551 xOut = xInfoStream->getOutputStream();
1554 catch(const uno::Exception& )
1556 SAL_WARN("basic", "Problem during storing of library index file!");
1557 // TODO: error handling?
1560 else
1562 // Export?
1563 bool bExport = !aTargetURL.isEmpty();
1564 Reference< XSimpleFileAccess3 > xSFI = mxSFI;
1565 if( rToUseSFI.is() )
1567 xSFI = rToUseSFI;
1569 OUString aLibInfoPath;
1570 if( bExport )
1572 INetURLObject aInetObj( aTargetURL );
1573 aInetObj.insertName( rLib.aName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1574 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1575 if( !xSFI->isFolder( aLibDirPath ) )
1577 xSFI->createFolder( aLibDirPath );
1579 aInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1580 aInetObj.setExtension( "xlb" );
1581 aLibInfoPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1583 else
1585 createAppLibraryFolder( pLib, rLib.aName );
1586 aLibInfoPath = pLib->maLibInfoFileURL;
1591 if( xSFI->exists( aLibInfoPath ) )
1593 xSFI->kill( aLibInfoPath );
1595 xOut = xSFI->openFileWrite( aLibInfoPath );
1597 catch(const Exception& )
1599 if( bExport )
1601 throw;
1603 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
1604 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1607 if( !xOut.is() )
1609 SAL_WARN("basic", "couldn't open output stream");
1610 return;
1612 xWriter->setOutputStream( xOut );
1613 xmlscript::exportLibrary( xWriter, rLib );
1617 bool SfxLibraryContainer::implLoadLibraryIndexFile( SfxLibrary* pLib,
1618 ::xmlscript::LibDescriptor& rLib,
1619 const uno::Reference< embed::XStorage >& xStorage,
1620 const OUString& aIndexFileName )
1622 Reference< XParser > xParser = xml::sax::Parser::create(mxContext);
1624 bool bStorage = false;
1625 if( pLib )
1627 bool bLink = pLib->mbLink;
1628 bStorage = xStorage.is() && !bLink;
1631 // Read info file
1632 uno::Reference< io::XInputStream > xInput;
1633 OUString aLibInfoPath;
1634 if( bStorage )
1636 aLibInfoPath = maInfoFileName + "-lb.xml";
1640 uno::Reference< io::XStream > xInfoStream =
1641 xStorage->openStreamElement( aLibInfoPath, embed::ElementModes::READ );
1642 xInput = xInfoStream->getInputStream();
1644 catch(const uno::Exception& )
1647 else
1649 // Create Input stream
1650 //String aLibInfoPath; // attention: THIS PROBLEM MUST BE REVIEWED BY SCRIPTING OWNER!!!
1652 if( pLib )
1654 createAppLibraryFolder( pLib, rLib.aName );
1655 aLibInfoPath = pLib->maLibInfoFileURL;
1657 else
1659 aLibInfoPath = aIndexFileName;
1663 xInput = mxSFI->openFileRead( aLibInfoPath );
1665 catch(const Exception& )
1667 xInput.clear();
1668 if( !GbMigrationSuppressErrors )
1670 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
1671 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1675 if( !xInput.is() )
1677 return false;
1680 InputSource source;
1681 source.aInputStream = xInput;
1682 source.sSystemId = aLibInfoPath;
1684 // start parsing
1687 xParser->setDocumentHandler( ::xmlscript::importLibrary( rLib ) );
1688 xParser->parseStream( source );
1690 catch(const Exception& )
1692 SAL_WARN("basic", "Parsing error");
1693 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aLibInfoPath );
1694 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
1695 return false;
1698 if( !pLib )
1700 Reference< XNameContainer > xLib = createLibrary( rLib.aName );
1701 pLib = static_cast< SfxLibrary* >( xLib.get() );
1702 pLib->mbLoaded = false;
1703 rLib.aStorageURL = aIndexFileName;
1704 checkStorageURL( rLib.aStorageURL, pLib->maLibInfoFileURL, pLib->maStorageURL,
1705 pLib->maUnexpandedStorageURL );
1707 implImportLibDescriptor( pLib, rLib );
1710 return true;
1713 void SfxLibraryContainer::implImportLibDescriptor( SfxLibrary* pLib,
1714 ::xmlscript::LibDescriptor const & rLib )
1716 if( !pLib->mbInitialised )
1718 sal_Int32 nElementCount = rLib.aElementNames.getLength();
1719 const OUString* pElementNames = rLib.aElementNames.getConstArray();
1720 Any aDummyElement = createEmptyLibraryElement();
1721 for( sal_Int32 i = 0 ; i < nElementCount ; i++ )
1723 pLib->maNameContainer->insertByName( pElementNames[i], aDummyElement );
1725 pLib->mbPasswordProtected = rLib.bPasswordProtected;
1726 pLib->mbReadOnly = rLib.bReadOnly;
1727 pLib->mbPreload = rLib.bPreload;
1728 pLib->implSetModified( false );
1729 pLib->mbInitialised = true;
1734 // Methods of new XLibraryStorage interface?
1735 void SfxLibraryContainer::storeLibraries_Impl( const uno::Reference< embed::XStorage >& i_rStorage,
1736 bool bComplete )
1738 const Sequence< OUString > aNames = maNameContainer->getElementNames();
1739 const sal_Int32 nNameCount = aNames.getLength();
1740 const OUString* pName = aNames.getConstArray();
1741 const OUString* pNamesEnd = aNames.getConstArray() + nNameCount;
1743 // Don't count libs from shared index file
1744 sal_Int32 nLibsToSave = nNameCount;
1745 for( ; pName != pNamesEnd; ++pName )
1747 SfxLibrary* pImplLib = getImplLib( *pName );
1748 if( pImplLib->mbSharedIndexFile || pImplLib->mbExtension )
1750 nLibsToSave--;
1753 // Write to storage?
1754 bool bStorage = i_rStorage.is();
1755 uno::Reference< embed::XStorage > xSourceLibrariesStor;
1756 uno::Reference< embed::XStorage > xTargetLibrariesStor;
1757 OUString sTempTargetStorName;
1758 const bool bInplaceStorage = bStorage && ( i_rStorage == mxStorage );
1760 if( nLibsToSave == 0 )
1762 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
1764 mxStorage->removeElement(maLibrariesDir);
1766 return;
1769 if ( bStorage )
1771 // Don't write if only empty standard lib exists
1772 if ( ( nLibsToSave == 1 ) && ( aNames[0] == "Standard" ) )
1774 Any aLibAny = maNameContainer->getByName( aNames[0] );
1775 Reference< XNameAccess > xNameAccess;
1776 aLibAny >>= xNameAccess;
1777 if ( ! xNameAccess->hasElements() )
1779 if ( bInplaceStorage && mxStorage->hasByName(maLibrariesDir) )
1781 mxStorage->removeElement(maLibrariesDir);
1783 return;
1787 // create the empty target storage
1790 OUString sTargetLibrariesStoreName;
1791 if ( bInplaceStorage )
1793 // create a temporary target storage
1794 const OUStringBuffer aTempTargetNameBase = maLibrariesDir + "_temp_";
1795 sal_Int32 index = 0;
1798 OUStringBuffer aTempTargetName( aTempTargetNameBase );
1799 aTempTargetName.append( index++ );
1801 sTargetLibrariesStoreName = aTempTargetName.makeStringAndClear();
1802 if ( !i_rStorage->hasByName( sTargetLibrariesStoreName ) )
1804 break;
1807 while ( true );
1808 sTempTargetStorName = sTargetLibrariesStoreName;
1810 else
1812 sTargetLibrariesStoreName = maLibrariesDir;
1813 if ( i_rStorage->hasByName( sTargetLibrariesStoreName ) )
1815 i_rStorage->removeElement( sTargetLibrariesStoreName );
1819 xTargetLibrariesStor.set( i_rStorage->openStorageElement( sTargetLibrariesStoreName, embed::ElementModes::READWRITE ), UNO_SET_THROW );
1821 catch( const uno::Exception& )
1823 DBG_UNHANDLED_EXCEPTION("basic");
1824 return;
1827 // open the source storage which might be used to copy yet-unmodified libraries
1830 if ( mxStorage->hasByName( maLibrariesDir ) || bInplaceStorage )
1832 xSourceLibrariesStor = mxStorage->openStorageElement( maLibrariesDir,
1833 bInplaceStorage ? embed::ElementModes::READWRITE : embed::ElementModes::READ );
1836 catch( const uno::Exception& )
1838 DBG_UNHANDLED_EXCEPTION("basic");
1839 return;
1843 int iArray = 0;
1844 pName = aNames.getConstArray();
1845 ::xmlscript::LibDescriptor aLibDescriptorForExtensionLibs;
1846 std::unique_ptr< ::xmlscript::LibDescriptorArray > pLibArray(new ::xmlscript::LibDescriptorArray(nLibsToSave));
1847 for( ; pName != pNamesEnd; ++pName )
1849 SfxLibrary* pImplLib = getImplLib( *pName );
1850 if( pImplLib->mbSharedIndexFile )
1852 continue;
1854 const bool bExtensionLib = pImplLib->mbExtension;
1855 ::xmlscript::LibDescriptor& rLib = bExtensionLib ?
1856 aLibDescriptorForExtensionLibs : pLibArray->mpLibs[iArray];
1857 if( !bExtensionLib )
1859 iArray++;
1861 rLib.aName = *pName;
1863 rLib.bLink = pImplLib->mbLink;
1864 if( !bStorage || pImplLib->mbLink )
1866 rLib.aStorageURL = ( pImplLib->maUnexpandedStorageURL.getLength() ) ?
1867 pImplLib->maUnexpandedStorageURL : pImplLib->maLibInfoFileURL;
1869 rLib.bReadOnly = pImplLib->mbReadOnly;
1870 rLib.bPreload = pImplLib->mbPreload;
1871 rLib.bPasswordProtected = pImplLib->mbPasswordProtected;
1872 rLib.aElementNames = pImplLib->getElementNames();
1874 if( pImplLib->implIsModified() || bComplete )
1876 // Testing pImplLib->implIsModified() is not reliable,
1877 // IMHO the value of pImplLib->implIsModified() should
1878 // reflect whether the library ( in-memory ) model
1879 // is in sync with the library container's own storage. Currently
1880 // whenever the library model is written to *any* storage
1881 // pImplLib->implSetModified( sal_False ) is called
1882 // The way the code works, especially the way that sfx uses
1883 // temp storage when saving ( and later sets the root storage of the
1884 // library container ) and similar madness in dbaccess means some surgery
1885 // is required to make it possible to successfully use this optimisation
1886 // It would be possible to do the implSetModified() call below only
1887 // conditionally, but that would require an additional boolean to be
1888 // passed in via the XStorageBasedDocument::storeLibrariesToStorage()...
1889 // fdo#68983: If there's a password and the password is not known, only
1890 // copying the storage works!
1891 // Can we simply copy the storage?
1892 bool isCopyStorage = !mbOldInfoFormat && !mbOasis2OOoFormat
1893 && !pImplLib->isLoadedStorable()
1894 && xSourceLibrariesStor.is() /* null for user profile */;
1895 if (isCopyStorage)
1899 (void)xSourceLibrariesStor->isStorageElement(rLib.aName);
1901 catch (container::NoSuchElementException const&)
1903 isCopyStorage = false;
1906 if (isCopyStorage)
1910 xSourceLibrariesStor->copyElementTo( rLib.aName, xTargetLibrariesStor, rLib.aName );
1912 catch( const uno::Exception& )
1914 DBG_UNHANDLED_EXCEPTION("basic");
1915 // TODO: error handling?
1918 else
1920 uno::Reference< embed::XStorage > xLibraryStor;
1921 if( bStorage )
1923 #if OSL_DEBUG_LEVEL > 0
1926 #endif
1927 xLibraryStor = xTargetLibrariesStor->openStorageElement(
1928 rLib.aName,
1929 embed::ElementModes::READWRITE );
1930 #if OSL_DEBUG_LEVEL > 0
1932 catch(const uno::Exception& )
1934 TOOLS_WARN_EXCEPTION(
1935 "basic",
1936 "couldn't create sub storage for library \"" << rLib.aName << "\"");
1937 throw;
1939 #endif
1942 // Maybe lib is not loaded?!
1943 if( bComplete )
1945 loadLibrary( rLib.aName );
1947 if( pImplLib->mbPasswordProtected )
1949 implStorePasswordLibrary( pImplLib, rLib.aName, xLibraryStor, uno::Reference< task::XInteractionHandler >() );
1950 // TODO: Check return value
1952 else
1954 implStoreLibrary( pImplLib, rLib.aName, xLibraryStor );
1956 implStoreLibraryIndexFile( pImplLib, rLib, xLibraryStor );
1957 if( bStorage )
1961 uno::Reference< embed::XTransactedObject > xTransact( xLibraryStor, uno::UNO_QUERY_THROW );
1962 xTransact->commit();
1964 catch(const uno::Exception& )
1966 DBG_UNHANDLED_EXCEPTION("basic");
1967 // TODO: error handling
1968 throw;
1972 maModifiable.setModified( true );
1973 pImplLib->implSetModified( false );
1976 // For container info ReadOnly refers to mbReadOnlyLink
1977 rLib.bReadOnly = pImplLib->mbReadOnlyLink;
1980 // if we did an in-place save into a storage (i.e. a save into the storage we were already based on),
1981 // then we need to clean up the temporary storage we used for this
1982 if ( bInplaceStorage && !sTempTargetStorName.isEmpty() )
1984 SAL_WARN_IF(
1985 !xSourceLibrariesStor.is(), "basic",
1986 ("SfxLibrariesContainer::storeLibraries_impl: unexpected: we should"
1987 " have a source storage here!"));
1990 // for this, we first remove everything from the source storage, then copy the complete content
1991 // from the temporary target storage. From then on, what used to be the "source storage" becomes
1992 // the "target storage" for all subsequent operations.
1994 // (We cannot simply remove the storage, denoted by maLibrariesDir, from i_rStorage - there might be
1995 // open references to it.)
1997 if ( xSourceLibrariesStor.is() )
1999 // remove
2000 const Sequence< OUString > aRemoveNames( xSourceLibrariesStor->getElementNames() );
2001 for ( auto const & removeName : aRemoveNames )
2003 xSourceLibrariesStor->removeElement( removeName );
2006 // copy
2007 const Sequence< OUString > aCopyNames( xTargetLibrariesStor->getElementNames() );
2008 for ( auto const & copyName : aCopyNames )
2010 xTargetLibrariesStor->copyElementTo( copyName, xSourceLibrariesStor, copyName );
2014 // close and remove temp target
2015 xTargetLibrariesStor->dispose();
2016 i_rStorage->removeElement( sTempTargetStorName );
2017 xTargetLibrariesStor.clear();
2018 sTempTargetStorName.clear();
2020 // adjust target
2021 xTargetLibrariesStor = xSourceLibrariesStor;
2022 xSourceLibrariesStor.clear();
2024 catch( const Exception& )
2026 DBG_UNHANDLED_EXCEPTION("basic");
2027 throw;
2031 if( !mbOldInfoFormat && !maModifiable.isModified() )
2033 return;
2035 maModifiable.setModified( false );
2036 mbOldInfoFormat = false;
2038 // Write library container info
2039 // Create sax writer
2040 Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext);
2042 // Write info file
2043 uno::Reference< io::XOutputStream > xOut;
2044 uno::Reference< io::XStream > xInfoStream;
2045 if( bStorage )
2047 OUString aStreamName = maInfoFileName + "-lc.xml";
2051 xInfoStream = xTargetLibrariesStor->openStreamElement( aStreamName, embed::ElementModes::READWRITE );
2052 uno::Reference< beans::XPropertySet > xProps( xInfoStream, uno::UNO_QUERY_THROW );
2053 xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) );
2055 // #87671 Allow encryption
2056 xProps->setPropertyValue("UseCommonStoragePasswordEncryption", uno::Any( true ) );
2058 xOut = xInfoStream->getOutputStream();
2060 catch(const uno::Exception& )
2062 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2065 else
2067 // Create Output stream
2068 INetURLObject aLibInfoInetObj( maLibraryPath.getToken(1, ';') );
2069 aLibInfoInetObj.insertName( maInfoFileName, false, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
2070 aLibInfoInetObj.setExtension( "xlc" );
2071 OUString aLibInfoPath( aLibInfoInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2075 if( mxSFI->exists( aLibInfoPath ) )
2077 mxSFI->kill( aLibInfoPath );
2079 xOut = mxSFI->openFileWrite( aLibInfoPath );
2081 catch(const Exception& )
2083 xOut.clear();
2084 SfxErrorContext aEc( ERRCTX_SFX_SAVEDOC, aLibInfoPath );
2085 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2089 if( !xOut.is() )
2091 SAL_WARN("basic", "couldn't open output stream");
2092 return;
2095 xWriter->setOutputStream( xOut );
2099 xmlscript::exportLibraryContainer( xWriter, pLibArray.get() );
2100 if ( bStorage )
2102 uno::Reference< embed::XTransactedObject > xTransact( xTargetLibrariesStor, uno::UNO_QUERY_THROW );
2103 xTransact->commit();
2106 catch(const uno::Exception& )
2108 SAL_WARN("basic", "Problem during storing of libraries!");
2109 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
2114 // Methods XElementAccess
2115 Type SAL_CALL SfxLibraryContainer::getElementType()
2117 LibraryContainerMethodGuard aGuard( *this );
2118 return maNameContainer->getElementType();
2121 sal_Bool SfxLibraryContainer::hasElements()
2123 LibraryContainerMethodGuard aGuard( *this );
2124 bool bRet = maNameContainer->hasElements();
2125 return bRet;
2128 // Methods XNameAccess
2129 Any SfxLibraryContainer::getByName( const OUString& aName )
2131 LibraryContainerMethodGuard aGuard( *this );
2132 Any aRetAny = maNameContainer->getByName( aName ) ;
2133 return aRetAny;
2136 Sequence< OUString > SfxLibraryContainer::getElementNames()
2138 LibraryContainerMethodGuard aGuard( *this );
2139 return maNameContainer->getElementNames();
2142 sal_Bool SfxLibraryContainer::hasByName( const OUString& aName )
2144 LibraryContainerMethodGuard aGuard( *this );
2145 return maNameContainer->hasByName( aName ) ;
2148 // Methods XLibraryContainer
2149 Reference< XNameContainer > SAL_CALL SfxLibraryContainer::createLibrary( const OUString& Name )
2151 LibraryContainerMethodGuard aGuard( *this );
2152 SfxLibrary* pNewLib = implCreateLibrary( Name );
2153 pNewLib->maLibElementFileExtension = maLibElementFileExtension;
2155 createVariableURL( pNewLib->maUnexpandedStorageURL, Name, maInfoFileName, true );
2157 Reference< XNameAccess > xNameAccess = static_cast< XNameAccess* >( pNewLib );
2158 Any aElement;
2159 aElement <<= xNameAccess;
2160 maNameContainer->insertByName( Name, aElement );
2161 maModifiable.setModified( true );
2162 Reference< XNameContainer > xRet( xNameAccess, UNO_QUERY );
2163 return xRet;
2166 Reference< XNameAccess > SAL_CALL SfxLibraryContainer::createLibraryLink
2167 ( const OUString& Name, const OUString& StorageURL, sal_Bool ReadOnly )
2169 LibraryContainerMethodGuard aGuard( *this );
2170 // TODO: Check other reasons to force ReadOnly status
2171 //if( !ReadOnly )
2175 OUString aLibInfoFileURL;
2176 OUString aLibDirURL;
2177 OUString aUnexpandedStorageURL;
2178 checkStorageURL( StorageURL, aLibInfoFileURL, aLibDirURL, aUnexpandedStorageURL );
2181 SfxLibrary* pNewLib = implCreateLibraryLink( Name, aLibInfoFileURL, aLibDirURL, ReadOnly );
2182 pNewLib->maLibElementFileExtension = maLibElementFileExtension;
2183 pNewLib->maUnexpandedStorageURL = aUnexpandedStorageURL;
2184 pNewLib->maOriginalStorageURL = StorageURL;
2186 uno::Reference< embed::XStorage > xDummyStor;
2187 ::xmlscript::LibDescriptor aLibDesc;
2188 implLoadLibraryIndexFile( pNewLib, aLibDesc, xDummyStor, OUString() );
2189 implImportLibDescriptor( pNewLib, aLibDesc );
2191 Reference< XNameAccess > xRet = static_cast< XNameAccess* >( pNewLib );
2192 Any aElement;
2193 aElement <<= xRet;
2194 maNameContainer->insertByName( Name, aElement );
2195 maModifiable.setModified( true );
2197 if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE" ) != -1 )
2199 pNewLib->mbExtension = true;
2201 else if( StorageURL.indexOf( "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE" ) != -1
2202 || StorageURL.indexOf( "vnd.sun.star.expand:$BUNDLED_EXTENSIONS" ) != -1 )
2204 pNewLib->mbExtension = true;
2205 pNewLib->mbReadOnly = true;
2208 return xRet;
2211 void SAL_CALL SfxLibraryContainer::removeLibrary( const OUString& Name )
2213 LibraryContainerMethodGuard aGuard( *this );
2214 // Get and hold library before removing
2215 Any aLibAny = maNameContainer->getByName( Name ) ;
2216 Reference< XNameAccess > xNameAccess;
2217 aLibAny >>= xNameAccess;
2218 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2219 if( pImplLib->mbReadOnly && !pImplLib->mbLink )
2221 throw IllegalArgumentException();
2223 // Remove from container
2224 maNameContainer->removeByName( Name );
2225 maModifiable.setModified( true );
2227 // Delete library files, but not for linked libraries
2228 if( !pImplLib->mbLink )
2230 if( mxStorage.is() )
2232 return;
2234 if( xNameAccess->hasElements() )
2236 Sequence< OUString > aNames = pImplLib->getElementNames();
2237 sal_Int32 nNameCount = aNames.getLength();
2238 const OUString* pNames = aNames.getConstArray();
2239 for( sal_Int32 i = 0 ; i < nNameCount ; ++i, ++pNames )
2241 pImplLib->removeElementWithoutChecks( *pNames, SfxLibrary::LibraryContainerAccess() );
2245 // Delete index file
2246 createAppLibraryFolder( pImplLib, Name );
2247 OUString aLibInfoPath = pImplLib->maLibInfoFileURL;
2250 if( mxSFI->exists( aLibInfoPath ) )
2252 mxSFI->kill( aLibInfoPath );
2255 catch(const Exception& ) {}
2257 // Delete folder if empty
2258 INetURLObject aInetObj( maLibraryPath.getToken(1, ';') );
2259 aInetObj.insertName( Name, true, INetURLObject::LAST_SEGMENT,
2260 INetURLObject::EncodeMechanism::All );
2261 OUString aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2265 if( mxSFI->isFolder( aLibDirPath ) )
2267 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
2268 sal_Int32 nCount = aContentSeq.getLength();
2269 if( !nCount )
2271 mxSFI->kill( aLibDirPath );
2275 catch(const Exception& )
2281 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLoaded( const OUString& Name )
2283 LibraryContainerMethodGuard aGuard( *this );
2284 SfxLibrary* pImplLib = getImplLib( Name );
2285 bool bRet = pImplLib->mbLoaded;
2286 return bRet;
2290 void SAL_CALL SfxLibraryContainer::loadLibrary( const OUString& Name )
2292 LibraryContainerMethodGuard aGuard( *this );
2293 Any aLibAny = maNameContainer->getByName( Name ) ;
2294 Reference< XNameAccess > xNameAccess;
2295 aLibAny >>= xNameAccess;
2296 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2298 bool bLoaded = pImplLib->mbLoaded;
2299 pImplLib->mbLoaded = true;
2300 if( !bLoaded && xNameAccess->hasElements() )
2302 if( pImplLib->mbPasswordProtected )
2304 implLoadPasswordLibrary( pImplLib, Name );
2305 return;
2308 bool bLink = pImplLib->mbLink;
2309 bool bStorage = mxStorage.is() && !bLink;
2311 uno::Reference< embed::XStorage > xLibrariesStor;
2312 uno::Reference< embed::XStorage > xLibraryStor;
2313 if( bStorage )
2315 #if OSL_DEBUG_LEVEL > 0
2318 #endif
2319 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
2320 SAL_WARN_IF(
2321 !xLibrariesStor.is(), "basic",
2322 ("The method must either throw exception or return a"
2323 " storage!"));
2324 if ( !xLibrariesStor.is() )
2326 throw uno::RuntimeException("null returned from openStorageElement");
2329 xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ );
2330 SAL_WARN_IF(
2331 !xLibraryStor.is(), "basic",
2332 ("The method must either throw exception or return a"
2333 " storage!"));
2334 if ( !xLibrariesStor.is() )
2336 throw uno::RuntimeException("null returned from openStorageElement");
2338 #if OSL_DEBUG_LEVEL > 0
2340 catch(const uno::Exception& )
2342 TOOLS_WARN_EXCEPTION(
2343 "basic",
2344 "couldn't open sub storage for library \"" << Name << "\"");
2345 throw;
2347 #endif
2350 Sequence< OUString > aNames = pImplLib->getElementNames();
2351 sal_Int32 nNameCount = aNames.getLength();
2352 const OUString* pNames = aNames.getConstArray();
2353 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
2355 OUString aElementName = pNames[ i ];
2357 OUString aFile;
2358 uno::Reference< io::XInputStream > xInStream;
2360 if( bStorage )
2362 uno::Reference< io::XStream > xElementStream;
2364 aFile = aElementName + ".xml";
2368 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
2370 catch(const uno::Exception& )
2373 if( !xElementStream.is() )
2375 // Check for EA2 document version with wrong extensions
2376 aFile = aElementName + "." + maLibElementFileExtension;
2379 xElementStream = xLibraryStor->openStreamElement( aFile, embed::ElementModes::READ );
2381 catch(const uno::Exception& )
2385 if ( xElementStream.is() )
2387 xInStream = xElementStream->getInputStream();
2389 if ( !xInStream.is() )
2391 SAL_WARN(
2392 "basic",
2393 "couldn't open library element stream - attempted to"
2394 " open library \"" << Name << '"');
2395 throw RuntimeException("couldn't open library element stream", *this);
2398 else
2400 OUString aLibDirPath = pImplLib->maStorageURL;
2401 INetURLObject aElementInetObj( aLibDirPath );
2402 aElementInetObj.insertName( aElementName, false,
2403 INetURLObject::LAST_SEGMENT,
2404 INetURLObject::EncodeMechanism::All );
2405 aElementInetObj.setExtension( maLibElementFileExtension );
2406 aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2409 Reference< XNameContainer > xLib( pImplLib );
2410 Any aAny = importLibraryElement( xLib, aElementName,
2411 aFile, xInStream );
2412 if( pImplLib->hasByName( aElementName ) )
2414 if( aAny.hasValue() )
2416 pImplLib->maNameContainer->replaceByName( aElementName, aAny );
2419 else
2421 pImplLib->maNameContainer->insertNoCheck(aElementName, aAny);
2424 pImplLib->implSetModified( false );
2428 // Methods XLibraryContainer2
2429 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryLink( const OUString& Name )
2431 LibraryContainerMethodGuard aGuard( *this );
2432 SfxLibrary* pImplLib = getImplLib( Name );
2433 bool bRet = pImplLib->mbLink;
2434 return bRet;
2437 OUString SAL_CALL SfxLibraryContainer::getLibraryLinkURL( const OUString& Name )
2439 LibraryContainerMethodGuard aGuard( *this );
2440 SfxLibrary* pImplLib = getImplLib( Name );
2441 bool bLink = pImplLib->mbLink;
2442 if( !bLink )
2444 throw IllegalArgumentException();
2446 OUString aRetStr = pImplLib->maLibInfoFileURL;
2447 return aRetStr;
2450 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryReadOnly( const OUString& Name )
2452 LibraryContainerMethodGuard aGuard( *this );
2453 SfxLibrary* pImplLib = getImplLib( Name );
2454 bool bRet = pImplLib->mbReadOnly || (pImplLib->mbLink && pImplLib->mbReadOnlyLink);
2455 return bRet;
2458 void SAL_CALL SfxLibraryContainer::setLibraryReadOnly( const OUString& Name, sal_Bool bReadOnly )
2460 LibraryContainerMethodGuard aGuard( *this );
2461 SfxLibrary* pImplLib = getImplLib( Name );
2462 if( pImplLib->mbLink )
2464 if( pImplLib->mbReadOnlyLink != bool(bReadOnly) )
2466 pImplLib->mbReadOnlyLink = bReadOnly;
2467 pImplLib->implSetModified( true );
2468 maModifiable.setModified( true );
2471 else
2473 if( pImplLib->mbReadOnly != bool(bReadOnly) )
2475 pImplLib->mbReadOnly = bReadOnly;
2476 pImplLib->implSetModified( true );
2481 void SAL_CALL SfxLibraryContainer::renameLibrary( const OUString& Name, const OUString& NewName )
2483 LibraryContainerMethodGuard aGuard( *this );
2484 if( maNameContainer->hasByName( NewName ) )
2486 throw ElementExistException();
2488 // Get and hold library before removing
2489 Any aLibAny = maNameContainer->getByName( Name ) ;
2491 // #i24094 Maybe lib is not loaded!
2492 Reference< XNameAccess > xNameAccess;
2493 aLibAny >>= xNameAccess;
2494 SfxLibrary* pImplLib = static_cast< SfxLibrary* >( xNameAccess.get() );
2495 if( pImplLib->mbPasswordProtected && !pImplLib->mbPasswordVerified )
2497 return; // Lib with unverified password cannot be renamed
2499 loadLibrary( Name );
2501 // Remove from container
2502 maNameContainer->removeByName( Name );
2503 maModifiable.setModified( true );
2505 // Rename library folder, but not for linked libraries
2506 bool bMovedSuccessful = true;
2508 // Rename files
2509 bool bStorage = mxStorage.is();
2510 if( !bStorage && !pImplLib->mbLink )
2512 bMovedSuccessful = false;
2514 OUString aLibDirPath = pImplLib->maStorageURL;
2516 INetURLObject aDestInetObj( maLibraryPath.getToken(1, ';'));
2517 aDestInetObj.insertName( NewName, true, INetURLObject::LAST_SEGMENT,
2518 INetURLObject::EncodeMechanism::All );
2519 OUString aDestDirPath = aDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2521 // Store new URL
2522 OUString aLibInfoFileURL = pImplLib->maLibInfoFileURL;
2523 checkStorageURL( aDestDirPath, pImplLib->maLibInfoFileURL, pImplLib->maStorageURL,
2524 pImplLib->maUnexpandedStorageURL );
2528 if( mxSFI->isFolder( aLibDirPath ) )
2530 if( !mxSFI->isFolder( aDestDirPath ) )
2532 mxSFI->createFolder( aDestDirPath );
2534 // Move index file
2537 if( mxSFI->exists( pImplLib->maLibInfoFileURL ) )
2539 mxSFI->kill( pImplLib->maLibInfoFileURL );
2541 mxSFI->move( aLibInfoFileURL, pImplLib->maLibInfoFileURL );
2543 catch(const Exception& )
2547 Sequence< OUString > aElementNames = xNameAccess->getElementNames();
2548 sal_Int32 nNameCount = aElementNames.getLength();
2549 const OUString* pNames = aElementNames.getConstArray();
2550 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
2552 OUString aElementName = pNames[ i ];
2554 INetURLObject aElementInetObj( aLibDirPath );
2555 aElementInetObj.insertName( aElementName, false,
2556 INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
2557 aElementInetObj.setExtension( maLibElementFileExtension );
2558 OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2560 INetURLObject aElementDestInetObj( aDestDirPath );
2561 aElementDestInetObj.insertName( aElementName, false,
2562 INetURLObject::LAST_SEGMENT,
2563 INetURLObject::EncodeMechanism::All );
2564 aElementDestInetObj.setExtension( maLibElementFileExtension );
2565 OUString aDestElementPath( aElementDestInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2569 if( mxSFI->exists( aDestElementPath ) )
2571 mxSFI->kill( aDestElementPath );
2573 mxSFI->move( aElementPath, aDestElementPath );
2575 catch(const Exception& )
2579 pImplLib->storeResourcesAsURL( aDestDirPath, NewName );
2581 // Delete folder if empty
2582 Sequence< OUString > aContentSeq = mxSFI->getFolderContents( aLibDirPath, true );
2583 sal_Int32 nCount = aContentSeq.getLength();
2584 if( !nCount )
2586 mxSFI->kill( aLibDirPath );
2589 bMovedSuccessful = true;
2590 pImplLib->implSetModified( true );
2593 catch(const Exception& )
2595 // Restore old library
2596 maNameContainer->insertByName( Name, aLibAny ) ;
2600 if( bStorage && !pImplLib->mbLink )
2602 pImplLib->implSetModified( true );
2604 if( bMovedSuccessful )
2606 maNameContainer->insertByName( NewName, aLibAny ) ;
2611 // Methods XInitialization
2612 void SAL_CALL SfxLibraryContainer::initialize( const Sequence< Any >& _rArguments )
2614 LibraryContainerMethodGuard aGuard( *this );
2615 sal_Int32 nArgCount = _rArguments.getLength();
2616 if ( nArgCount == 1 )
2618 OUString sInitialDocumentURL;
2619 Reference< XStorageBasedDocument > xDocument;
2620 if ( _rArguments[0] >>= sInitialDocumentURL )
2622 init( sInitialDocumentURL, nullptr );
2623 return;
2626 if ( _rArguments[0] >>= xDocument )
2628 initializeFromDocument( xDocument );
2629 return;
2633 throw IllegalArgumentException();
2636 void SfxLibraryContainer::initializeFromDocument( const Reference< XStorageBasedDocument >& _rxDocument )
2638 // check whether this is a valid OfficeDocument, and obtain the document's root storage
2639 Reference< XStorage > xDocStorage;
2642 Reference< XServiceInfo > xSI( _rxDocument, UNO_QUERY_THROW );
2643 if ( xSI->supportsService("com.sun.star.document.OfficeDocument"))
2645 xDocStorage.set( _rxDocument->getDocumentStorage(), UNO_SET_THROW );
2647 Reference< XModel > xDocument( _rxDocument, UNO_QUERY_THROW );
2648 Reference< XComponent > xDocComponent( _rxDocument, UNO_QUERY_THROW );
2650 mxOwnerDocument = xDocument;
2651 startComponentListening( xDocComponent );
2653 catch( const Exception& ) { }
2655 if ( !xDocStorage.is() )
2657 throw IllegalArgumentException();
2659 init( OUString(), xDocStorage );
2662 // OEventListenerAdapter
2663 void SfxLibraryContainer::_disposing( const EventObject& _rSource )
2665 #if OSL_DEBUG_LEVEL > 0
2666 Reference< XModel > xDocument( mxOwnerDocument.get(), UNO_QUERY );
2667 SAL_WARN_IF(
2668 xDocument != _rSource.Source || !xDocument.is(), "basic",
2669 "SfxLibraryContainer::_disposing: where does this come from?");
2670 #else
2671 (void)_rSource;
2672 #endif
2673 dispose();
2676 // OComponentHelper
2677 void SAL_CALL SfxLibraryContainer::disposing()
2679 Reference< XModel > xModel = mxOwnerDocument;
2680 EventObject aEvent( xModel.get() );
2681 maVBAScriptListeners.disposing( aEvent );
2682 stopAllComponentListening();
2683 mxOwnerDocument.clear();
2686 // Methods XLibraryContainerPassword
2687 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordProtected( const OUString& )
2689 return false;
2692 sal_Bool SAL_CALL SfxLibraryContainer::isLibraryPasswordVerified( const OUString& )
2694 throw IllegalArgumentException();
2697 sal_Bool SAL_CALL SfxLibraryContainer::verifyLibraryPassword( const OUString&, const OUString& )
2699 throw IllegalArgumentException();
2702 void SAL_CALL SfxLibraryContainer::changeLibraryPassword(const OUString&, const OUString&, const OUString& )
2704 throw IllegalArgumentException();
2707 // Methods XContainer
2708 void SAL_CALL SfxLibraryContainer::addContainerListener( const Reference< XContainerListener >& xListener )
2710 LibraryContainerMethodGuard aGuard( *this );
2711 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
2712 maNameContainer->addContainerListener( xListener );
2715 void SAL_CALL SfxLibraryContainer::removeContainerListener( const Reference< XContainerListener >& xListener )
2717 LibraryContainerMethodGuard aGuard( *this );
2718 maNameContainer->removeContainerListener( xListener );
2721 // Methods XLibraryContainerExport
2722 void SAL_CALL SfxLibraryContainer::exportLibrary( const OUString& Name, const OUString& URL,
2723 const Reference< XInteractionHandler >& Handler )
2725 LibraryContainerMethodGuard aGuard( *this );
2726 SfxLibrary* pImplLib = getImplLib( Name );
2728 Reference< XSimpleFileAccess3 > xToUseSFI;
2729 if( Handler.is() )
2731 xToUseSFI = ucb::SimpleFileAccess::create( mxContext );
2732 xToUseSFI->setInteractionHandler( Handler );
2735 // Maybe lib is not loaded?!
2736 loadLibrary( Name );
2738 uno::Reference< css::embed::XStorage > xDummyStor;
2739 if( pImplLib->mbPasswordProtected )
2741 implStorePasswordLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
2743 else
2745 implStoreLibrary( pImplLib, Name, xDummyStor, URL, xToUseSFI, Handler );
2747 ::xmlscript::LibDescriptor aLibDesc;
2748 aLibDesc.aName = Name;
2749 aLibDesc.bLink = false; // Link status gets lost?
2750 aLibDesc.bReadOnly = pImplLib->mbReadOnly;
2751 aLibDesc.bPreload = false; // Preload status gets lost?
2752 aLibDesc.bPasswordProtected = pImplLib->mbPasswordProtected;
2753 aLibDesc.aElementNames = pImplLib->getElementNames();
2755 implStoreLibraryIndexFile( pImplLib, aLibDesc, xDummyStor, URL, xToUseSFI );
2758 OUString SfxLibraryContainer::expand_url( const OUString& url )
2760 if (url.startsWithIgnoreAsciiCase( "vnd.sun.star.expand:" ))
2762 return comphelper::getExpandedUri(mxContext, url);
2764 else if( mxStringSubstitution.is() )
2766 OUString ret( mxStringSubstitution->substituteVariables( url, false ) );
2767 return ret;
2769 else
2771 return url;
2775 //XLibraryContainer3
2776 OUString SAL_CALL SfxLibraryContainer::getOriginalLibraryLinkURL( const OUString& Name )
2778 LibraryContainerMethodGuard aGuard( *this );
2779 SfxLibrary* pImplLib = getImplLib( Name );
2780 bool bLink = pImplLib->mbLink;
2781 if( !bLink )
2783 throw IllegalArgumentException();
2785 OUString aRetStr = pImplLib->maOriginalStorageURL;
2786 return aRetStr;
2790 // XVBACompatibility
2791 sal_Bool SAL_CALL SfxLibraryContainer::getVBACompatibilityMode()
2793 return mbVBACompat;
2796 void SAL_CALL SfxLibraryContainer::setVBACompatibilityMode( sal_Bool _vbacompatmodeon )
2798 /* The member variable mbVBACompat must be set first, the following call
2799 to getBasicManager() may call getVBACompatibilityMode() which returns
2800 this value. */
2801 mbVBACompat = _vbacompatmodeon;
2802 if( BasicManager* pBasMgr = getBasicManager() )
2804 // get the standard library
2805 OUString aLibName = pBasMgr->GetName();
2806 if ( aLibName.isEmpty())
2808 aLibName = "Standard";
2810 if( StarBASIC* pBasic = pBasMgr->GetLib( aLibName ) )
2812 pBasic->SetVBAEnabled( _vbacompatmodeon );
2814 /* If in VBA compatibility mode, force creation of the VBA Globals
2815 object. Each application will create an instance of its own
2816 implementation and store it in its Basic manager. Implementations
2817 will do all necessary additional initialization, such as
2818 registering the global "This***Doc" UNO constant, starting the
2819 document events processor etc.
2821 if( mbVBACompat ) try
2823 Reference< XModel > xModel( mxOwnerDocument ); // weak-ref -> ref
2824 Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
2825 xFactory->createInstance("ooo.vba.VBAGlobals");
2827 catch(const Exception& )
2833 void SAL_CALL SfxLibraryContainer::setProjectName( const OUString& _projectname )
2835 msProjectName = _projectname;
2836 BasicManager* pBasMgr = getBasicManager();
2837 // Temporary HACK
2838 // Some parts of the VBA handling ( e.g. in core basic )
2839 // code expect the name of the VBA project to be set as the name of
2840 // the basic manager. Provide fail back here.
2841 if( pBasMgr )
2843 pBasMgr->SetName( msProjectName );
2847 sal_Int32 SAL_CALL SfxLibraryContainer::getRunningVBAScripts()
2849 LibraryContainerMethodGuard aGuard( *this );
2850 return mnRunningVBAScripts;
2853 void SAL_CALL SfxLibraryContainer::addVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
2855 maVBAScriptListeners.addTypedListener( rxListener );
2858 void SAL_CALL SfxLibraryContainer::removeVBAScriptListener( const Reference< vba::XVBAScriptListener >& rxListener )
2860 maVBAScriptListeners.removeTypedListener( rxListener );
2863 void SAL_CALL SfxLibraryContainer::broadcastVBAScriptEvent( sal_Int32 nIdentifier, const OUString& rModuleName )
2865 // own lock for accessing the number of running scripts
2866 enterMethod();
2867 switch( nIdentifier )
2869 case vba::VBAScriptEventId::SCRIPT_STARTED:
2870 ++mnRunningVBAScripts;
2871 break;
2872 case vba::VBAScriptEventId::SCRIPT_STOPPED:
2873 --mnRunningVBAScripts;
2874 break;
2876 leaveMethod();
2878 Reference< XModel > xModel = mxOwnerDocument; // weak-ref -> ref
2879 vba::VBAScriptEvent aEvent( Reference<XInterface>(xModel, UNO_QUERY), nIdentifier, rModuleName );
2880 maVBAScriptListeners.notify( aEvent );
2883 // Methods XServiceInfo
2884 sal_Bool SAL_CALL SfxLibraryContainer::supportsService( const OUString& _rServiceName )
2886 return cppu::supportsService(this, _rServiceName);
2889 // Implementation class SfxLibrary
2891 // Ctor
2892 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
2893 const Reference< XSimpleFileAccess3 >& xSFI )
2894 : OComponentHelper( m_aMutex )
2895 , mxSFI( xSFI )
2896 , mrModifiable( _rModifiable )
2897 , maNameContainer( new NameContainer(aType) )
2898 , mbLoaded( true )
2899 , mbIsModified( true )
2900 , mbInitialised( false )
2901 , mbLink( false )
2902 , mbReadOnly( false )
2903 , mbReadOnlyLink( false )
2904 , mbPreload( false )
2905 , mbPasswordProtected( false )
2906 , mbPasswordVerified( false )
2907 , mbDoc50Password( false )
2908 , mbSharedIndexFile( false )
2909 , mbExtension( false )
2913 SfxLibrary::SfxLibrary( ModifiableHelper& _rModifiable, const Type& aType,
2914 const Reference< XSimpleFileAccess3 >& xSFI,
2915 const OUString& aLibInfoFileURL, const OUString& aStorageURL, bool ReadOnly )
2916 : OComponentHelper( m_aMutex )
2917 , mxSFI( xSFI )
2918 , mrModifiable( _rModifiable )
2919 , maNameContainer( new NameContainer(aType) )
2920 , mbLoaded( false )
2921 , mbIsModified( true )
2922 , mbInitialised( false )
2923 , maLibInfoFileURL( aLibInfoFileURL )
2924 , maStorageURL( aStorageURL )
2925 , mbLink( true )
2926 , mbReadOnly( false )
2927 , mbReadOnlyLink( ReadOnly )
2928 , mbPreload( false )
2929 , mbPasswordProtected( false )
2930 , mbPasswordVerified( false )
2931 , mbDoc50Password( false )
2932 , mbSharedIndexFile( false )
2933 , mbExtension( false )
2937 bool SfxLibrary::isLoadedStorable()
2939 return mbLoaded && (!mbPasswordProtected || mbPasswordVerified);
2942 void SfxLibrary::implSetModified( bool _bIsModified )
2944 if ( mbIsModified == _bIsModified )
2946 return;
2948 mbIsModified = _bIsModified;
2949 if ( mbIsModified )
2951 mrModifiable.setModified( true );
2955 // Methods XInterface
2956 Any SAL_CALL SfxLibrary::queryInterface( const Type& rType )
2958 Any aRet =
2959 ::cppu::queryInterface(
2960 rType,
2961 static_cast< XContainer * >( this ),
2962 static_cast< XNameContainer * >( this ),
2963 static_cast< XNameAccess * >( this ),
2964 static_cast< XElementAccess * >( this ),
2965 static_cast< XChangesNotifier * >( this ) );
2966 if( !aRet.hasValue() )
2968 aRet = OComponentHelper::queryInterface( rType );
2970 return aRet;
2973 // Methods XElementAccess
2974 Type SfxLibrary::getElementType()
2976 return maNameContainer->getElementType();
2979 sal_Bool SfxLibrary::hasElements()
2981 bool bRet = maNameContainer->hasElements();
2982 return bRet;
2985 // Methods XNameAccess
2986 Any SfxLibrary::getByName( const OUString& aName )
2988 impl_checkLoaded();
2990 Any aRetAny = maNameContainer->getByName( aName ) ;
2991 return aRetAny;
2994 Sequence< OUString > SfxLibrary::getElementNames()
2996 return maNameContainer->getElementNames();
2999 sal_Bool SfxLibrary::hasByName( const OUString& aName )
3001 bool bRet = maNameContainer->hasByName( aName );
3002 return bRet;
3005 void SfxLibrary::impl_checkReadOnly()
3007 if( mbReadOnly || (mbLink && mbReadOnlyLink) )
3009 throw IllegalArgumentException(
3010 "Library is readonly.",
3011 // TODO: resource
3012 *this, 0
3017 void SfxLibrary::impl_checkLoaded()
3019 if ( !mbLoaded )
3021 throw WrappedTargetException(
3022 OUString(),
3023 *this,
3024 Any( LibraryNotLoadedException(
3025 OUString(),
3026 *this
3032 // Methods XNameReplace
3033 void SfxLibrary::replaceByName( const OUString& aName, const Any& aElement )
3035 impl_checkReadOnly();
3036 impl_checkLoaded();
3038 SAL_WARN_IF(
3039 !isLibraryElementValid(aElement), "basic",
3040 "SfxLibrary::replaceByName: replacing element is invalid!");
3042 maNameContainer->replaceByName( aName, aElement );
3043 implSetModified( true );
3047 // Methods XNameContainer
3048 void SfxLibrary::insertByName( const OUString& aName, const Any& aElement )
3050 impl_checkReadOnly();
3051 impl_checkLoaded();
3053 SAL_WARN_IF(
3054 !isLibraryElementValid(aElement), "basic",
3055 "SfxLibrary::insertByName: to-be-inserted element is invalid!");
3057 maNameContainer->insertByName( aName, aElement );
3058 implSetModified( true );
3061 void SfxLibrary::impl_removeWithoutChecks( const OUString& _rElementName )
3063 maNameContainer->removeByName( _rElementName );
3064 implSetModified( true );
3066 // Remove element file
3067 if( !maStorageURL.isEmpty() )
3069 INetURLObject aElementInetObj( maStorageURL );
3070 aElementInetObj.insertName( _rElementName, false,
3071 INetURLObject::LAST_SEGMENT,
3072 INetURLObject::EncodeMechanism::All );
3073 aElementInetObj.setExtension( maLibElementFileExtension );
3074 OUString aFile = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
3078 if( mxSFI->exists( aFile ) )
3080 mxSFI->kill( aFile );
3083 catch(const Exception& )
3085 DBG_UNHANDLED_EXCEPTION("basic");
3090 void SfxLibrary::removeByName( const OUString& Name )
3092 impl_checkReadOnly();
3093 impl_checkLoaded();
3094 impl_removeWithoutChecks( Name );
3097 // XTypeProvider
3098 Sequence< Type > SfxLibrary::getTypes()
3100 static OTypeCollection ourTypes_NameContainer(
3101 cppu::UnoType<XNameContainer>::get(),
3102 cppu::UnoType<XContainer>::get(),
3103 cppu::UnoType<XChangesNotifier>::get(),
3104 OComponentHelper::getTypes() );
3106 return ourTypes_NameContainer.getTypes();
3110 Sequence< sal_Int8 > SfxLibrary::getImplementationId()
3112 return css::uno::Sequence<sal_Int8>();
3115 // Methods XContainer
3116 void SAL_CALL SfxLibrary::addContainerListener( const Reference< XContainerListener >& xListener )
3118 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
3119 maNameContainer->addContainerListener( xListener );
3122 void SAL_CALL SfxLibrary::removeContainerListener( const Reference< XContainerListener >& xListener )
3124 maNameContainer->removeContainerListener( xListener );
3127 // Methods XChangesNotifier
3128 void SAL_CALL SfxLibrary::addChangesListener( const Reference< XChangesListener >& xListener )
3130 maNameContainer->setEventSource( static_cast< XInterface* >( static_cast<OWeakObject*>(this) ) );
3131 maNameContainer->addChangesListener( xListener );
3134 void SAL_CALL SfxLibrary::removeChangesListener( const Reference< XChangesListener >& xListener )
3136 maNameContainer->removeChangesListener( xListener );
3140 // Implementation class ScriptExtensionIterator
3142 #define sBasicLibMediaType "application/vnd.sun.star.basic-library"
3143 #define sDialogLibMediaType "application/vnd.sun.star.dialog-library"
3145 ScriptExtensionIterator::ScriptExtensionIterator()
3146 : m_xContext( comphelper::getProcessComponentContext() )
3147 , m_eState( USER_EXTENSIONS )
3148 , m_bUserPackagesLoaded( false )
3149 , m_bSharedPackagesLoaded( false )
3150 , m_bBundledPackagesLoaded( false )
3151 , m_iUserPackage( 0 )
3152 , m_iSharedPackage( 0 )
3153 , m_iBundledPackage( 0 )
3154 , m_pScriptSubPackageIterator( nullptr )
3157 OUString ScriptExtensionIterator::nextBasicOrDialogLibrary( bool& rbPureDialogLib )
3159 OUString aRetLib;
3161 while( aRetLib.isEmpty() && m_eState != END_REACHED )
3163 switch( m_eState )
3165 case USER_EXTENSIONS:
3167 Reference< deployment::XPackage > xScriptPackage =
3168 implGetNextUserScriptPackage( rbPureDialogLib );
3169 if( !xScriptPackage.is() )
3171 break;
3173 aRetLib = xScriptPackage->getURL();
3174 break;
3177 case SHARED_EXTENSIONS:
3179 Reference< deployment::XPackage > xScriptPackage =
3180 implGetNextSharedScriptPackage( rbPureDialogLib );
3181 if( !xScriptPackage.is() )
3183 break;
3185 aRetLib = xScriptPackage->getURL();
3186 break;
3188 case BUNDLED_EXTENSIONS:
3190 Reference< deployment::XPackage > xScriptPackage =
3191 implGetNextBundledScriptPackage( rbPureDialogLib );
3192 if( !xScriptPackage.is() )
3194 break;
3196 aRetLib = xScriptPackage->getURL();
3197 break;
3199 case END_REACHED:
3200 SAL_WARN(
3201 "basic",
3202 ("ScriptExtensionIterator::nextBasicOrDialogLibrary():"
3203 " Invalid case END_REACHED"));
3204 break;
3208 return aRetLib;
3211 ScriptSubPackageIterator::ScriptSubPackageIterator( Reference< deployment::XPackage > const & xMainPackage )
3212 : m_xMainPackage( xMainPackage )
3213 , m_bIsValid( false )
3214 , m_bIsBundle( false )
3215 , m_nSubPkgCount( 0 )
3216 , m_iNextSubPkg( 0 )
3218 if( !m_xMainPackage.is() )
3220 return;
3222 // Check if parent package is registered
3223 beans::Optional< beans::Ambiguous<sal_Bool> > option( m_xMainPackage->isRegistered
3224 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
3225 bool bRegistered = false;
3226 if( option.IsPresent )
3228 beans::Ambiguous<sal_Bool> const & reg = option.Value;
3229 if( !reg.IsAmbiguous && reg.Value )
3231 bRegistered = true;
3234 if( bRegistered )
3236 m_bIsValid = true;
3237 if( m_xMainPackage->isBundle() )
3239 m_bIsBundle = true;
3240 m_aSubPkgSeq = m_xMainPackage->getBundle( Reference<task::XAbortChannel>(),
3241 Reference<ucb::XCommandEnvironment>() );
3242 m_nSubPkgCount = m_aSubPkgSeq.getLength();
3247 Reference< deployment::XPackage > ScriptSubPackageIterator::getNextScriptSubPackage( bool& rbPureDialogLib )
3249 rbPureDialogLib = false;
3251 Reference< deployment::XPackage > xScriptPackage;
3252 if( !m_bIsValid )
3254 return xScriptPackage;
3256 if( m_bIsBundle )
3258 const Reference< deployment::XPackage >* pSeq = m_aSubPkgSeq.getConstArray();
3259 sal_Int32 iPkg;
3260 for( iPkg = m_iNextSubPkg ; iPkg < m_nSubPkgCount ; ++iPkg )
3262 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
3263 xScriptPackage = implDetectScriptPackage( xSubPkg, rbPureDialogLib );
3264 if( xScriptPackage.is() )
3266 break;
3269 m_iNextSubPkg = iPkg + 1;
3271 else
3273 xScriptPackage = implDetectScriptPackage( m_xMainPackage, rbPureDialogLib );
3274 m_bIsValid = false; // No more script packages
3277 return xScriptPackage;
3280 Reference< deployment::XPackage > ScriptSubPackageIterator::implDetectScriptPackage ( const Reference< deployment::XPackage >& rPackage,
3281 bool& rbPureDialogLib )
3283 Reference< deployment::XPackage > xScriptPackage;
3285 if( rPackage.is() )
3287 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = rPackage->getPackageType();
3288 OUString aMediaType = xPackageTypeInfo->getMediaType();
3289 if ( aMediaType == sBasicLibMediaType )
3291 xScriptPackage = rPackage;
3293 else if ( aMediaType == sDialogLibMediaType )
3295 rbPureDialogLib = true;
3296 xScriptPackage = rPackage;
3300 return xScriptPackage;
3303 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextUserScriptPackage( bool& rbPureDialogLib )
3305 Reference< deployment::XPackage > xScriptPackage;
3307 if( !m_bUserPackagesLoaded )
3311 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
3312 m_aUserPackagesSeq = xManager->getDeployedExtensions("user",
3313 Reference< task::XAbortChannel >(),
3314 Reference< ucb::XCommandEnvironment >() );
3316 catch(const css::uno::DeploymentException& )
3318 // Special Office installations may not contain deployment code
3319 m_eState = END_REACHED;
3320 return xScriptPackage;
3323 m_bUserPackagesLoaded = true;
3326 if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
3328 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
3330 else
3332 if( m_pScriptSubPackageIterator == nullptr )
3334 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
3335 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage ];
3336 SAL_WARN_IF(
3337 !xPackage.is(), "basic",
3338 ("ScriptExtensionIterator::implGetNextUserScriptPackage():"
3339 " Invalid package"));
3340 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3343 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3344 if( !xScriptPackage.is() )
3346 delete m_pScriptSubPackageIterator;
3347 m_pScriptSubPackageIterator = nullptr;
3348 m_iUserPackage++;
3352 return xScriptPackage;
3355 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextSharedScriptPackage( bool& rbPureDialogLib )
3357 Reference< deployment::XPackage > xScriptPackage;
3359 if( !m_bSharedPackagesLoaded )
3363 Reference< XExtensionManager > xSharedManager = ExtensionManager::get( m_xContext );
3364 m_aSharedPackagesSeq = xSharedManager->getDeployedExtensions("shared",
3365 Reference< task::XAbortChannel >(),
3366 Reference< ucb::XCommandEnvironment >() );
3368 catch(const css::uno::DeploymentException& )
3370 // Special Office installations may not contain deployment code
3371 return xScriptPackage;
3374 m_bSharedPackagesLoaded = true;
3377 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
3379 m_eState = BUNDLED_EXTENSIONS;
3381 else
3383 if( m_pScriptSubPackageIterator == nullptr )
3385 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
3386 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage ];
3387 SAL_WARN_IF(
3388 !xPackage.is(), "basic",
3389 ("ScriptExtensionIterator::implGetNextSharedScriptPackage():"
3390 " Invalid package"));
3391 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3394 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3395 if( !xScriptPackage.is() )
3397 delete m_pScriptSubPackageIterator;
3398 m_pScriptSubPackageIterator = nullptr;
3399 m_iSharedPackage++;
3403 return xScriptPackage;
3406 Reference< deployment::XPackage > ScriptExtensionIterator::implGetNextBundledScriptPackage( bool& rbPureDialogLib )
3408 Reference< deployment::XPackage > xScriptPackage;
3410 if( !m_bBundledPackagesLoaded )
3414 Reference< XExtensionManager > xManager = ExtensionManager::get( m_xContext );
3415 m_aBundledPackagesSeq = xManager->getDeployedExtensions("bundled",
3416 Reference< task::XAbortChannel >(),
3417 Reference< ucb::XCommandEnvironment >() );
3419 catch(const css::uno::DeploymentException& )
3421 // Special Office installations may not contain deployment code
3422 return xScriptPackage;
3425 m_bBundledPackagesLoaded = true;
3428 if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
3430 m_eState = END_REACHED;
3432 else
3434 if( m_pScriptSubPackageIterator == nullptr )
3436 const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
3437 Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage ];
3438 SAL_WARN_IF(
3439 !xPackage.is(), "basic",
3440 ("ScriptExtensionIterator::implGetNextBundledScriptPackage():"
3441 " Invalid package"));
3442 m_pScriptSubPackageIterator = new ScriptSubPackageIterator( xPackage );
3445 xScriptPackage = m_pScriptSubPackageIterator->getNextScriptSubPackage( rbPureDialogLib );
3446 if( !xScriptPackage.is() )
3448 delete m_pScriptSubPackageIterator;
3449 m_pScriptSubPackageIterator = nullptr;
3450 m_iBundledPackage++;
3454 return xScriptPackage;
3457 } // namespace basic
3459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */