1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include <uiconfiguration/uiconfigurationmanager.hxx>
31 #include <threadhelp/resetableguard.hxx>
32 #include <services.h>
33 #include <uielement/rootitemcontainer.hxx>
34 #include <uielement/constitemcontainer.hxx>
35 #include <uielement/uielementtypenames.hxx>
36 #include <framework/menuconfiguration.hxx>
37 #include <framework/toolboxconfiguration.hxx>
38 
39 #ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_
40 #include <framework/statusbarconfiguration.hxx>
41 #endif
42 
43 //_________________________________________________________________________________________________________________
44 //	interface includes
45 //_________________________________________________________________________________________________________________
46 #include <com/sun/star/ui/UIElementType.hpp>
47 #include <com/sun/star/ui/ConfigurationEvent.hpp>
48 #include <com/sun/star/lang/XInitialization.hpp>
49 #include <com/sun/star/lang/DisposedException.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/embed/ElementModes.hpp>
52 #include <com/sun/star/container/XNameAccess.hpp>
53 #include <com/sun/star/io/XStream.hpp>
54 #include <com/sun/star/embed/XTransactedObject.hpp>
55 
56 //_________________________________________________________________________________________________________________
57 //	other includes
58 //_________________________________________________________________________________________________________________
59 
60 #include <vcl/svapp.hxx>
61 #include <rtl/ustrbuf.hxx>
62 
63 //_________________________________________________________________________________________________________________
64 //	namespaces
65 //_________________________________________________________________________________________________________________
66 
67 using namespace com::sun::star::uno;
68 using namespace com::sun::star::io;
69 using namespace com::sun::star::embed;
70 using namespace com::sun::star::lang;
71 using namespace com::sun::star::container;
72 using namespace com::sun::star::beans;
73 using namespace ::com::sun::star::ui;
74 
75 namespace framework
76 {
77 
78 //*****************************************************************************************************************
79 //	XInterface, XTypeProvider, XServiceInfo
80 //*****************************************************************************************************************
81 DEFINE_XINTERFACE_7                    (    UIConfigurationManager                                                          ,
82                                             OWeakObject                                                                     ,
83                                             DIRECT_INTERFACE( css::lang::XTypeProvider                                      ),
84                                             DIRECT_INTERFACE( css::lang::XServiceInfo                                       ),
85                                             DIRECT_INTERFACE( css::lang::XComponent                                         ),
86                                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration                  ),
87 											DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager           ),
88                                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence       ),
89                                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationStorage           )
90 										)
91 
92 DEFINE_XTYPEPROVIDER_7                  (   UIConfigurationManager                                  ,
93                                             css::lang::XTypeProvider			                    ,
94                                             css::lang::XServiceInfo				                    ,
95                                             css::lang::XComponent                                   ,
96 											::com::sun::star::ui::XUIConfiguration            ,
97 											::com::sun::star::ui::XUIConfigurationManager     ,
98                                             ::com::sun::star::ui::XUIConfigurationPersistence ,
99                                             ::com::sun::star::ui::XUIConfigurationStorage
100 										)
101 
102 DEFINE_XSERVICEINFO_MULTISERVICE        (   UIConfigurationManager                      ,
103                                             ::cppu::OWeakObject                         ,
104                                             SERVICENAME_UICONFIGURATIONMANAGER	        ,
105 											IMPLEMENTATIONNAME_UICONFIGURATIONMANAGER
106 										)
107 
108 DEFINE_INIT_SERVICE                     (   UIConfigurationManager, {} )
109 
110 
111 // important: The order and position of the elements must match the constant
112 // definition of "::com::sun::star::ui::UIElementType"
113 static const char* UIELEMENTTYPENAMES[] =
114 {
115     "",  // Dummy value for unknown!
116     UIELEMENTTYPE_MENUBAR_NAME,
117     UIELEMENTTYPE_POPUPMENU_NAME,
118     UIELEMENTTYPE_TOOLBAR_NAME,
119     UIELEMENTTYPE_STATUSBAR_NAME,
120     UIELEMENTTYPE_FLOATINGWINDOW_NAME,
121     UIELEMENTTYPE_PROGRESSBAR_NAME,
122     UIELEMENTTYPE_TOOLPANEL_NAME
123 };
124 
125 static const char       RESOURCEURL_PREFIX[] = "private:resource/";
126 static const sal_Int32  RESOURCEURL_PREFIX_SIZE = 17;
127 
128 static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL )
129 {
130 
131     if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
132         ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
133     {
134         rtl::OUString aTmpStr     = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE );
135         sal_Int32     nIndex      = aTmpStr.indexOf( '/' );
136         if (( nIndex > 0 ) &&  ( aTmpStr.getLength() > nIndex ))
137         {
138             rtl::OUString aTypeStr( aTmpStr.copy( 0, nIndex ));
139             for ( int i = 0; i < UIElementType::COUNT; i++ )
140             {
141                 if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] ))
142                     return sal_Int16( i );
143             }
144         }
145     }
146 
147     return UIElementType::UNKNOWN;
148 }
149 
150 static rtl::OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL )
151 {
152     if (( aResourceURL.indexOf( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
153         ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
154     {
155         sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' );
156         if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength()))
157             return aResourceURL.copy( nIndex+1 );
158     }
159 
160     return rtl::OUString();
161 }
162 
163 void UIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType )
164 {
165     // preload list of element types on demand
166     impl_preloadUIElementTypeList( nElementType );
167 
168     UIElementDataHashMap& rUserElements = m_aUIElements[nElementType].aElementsHashMap;
169     UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin();
170 
171     while ( pUserIter != rUserElements.end() )
172     {
173         UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType );
174         if ( pDataSettings && !pDataSettings->bDefault )
175         {
176             // Retrieve user interface name from XPropertySet interface
177             rtl::OUString aUIName;
178             Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
179             if ( xPropSet.is() )
180             {
181                 Any a = xPropSet->getPropertyValue( m_aPropUIName );
182                 a >>= aUIName;
183             }
184 
185             UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName );
186             aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
187         }
188         ++pUserIter;
189     }
190 }
191 
192 void UIConfigurationManager::impl_preloadUIElementTypeList( sal_Int16 nElementType )
193 {
194     UIElementType& rElementTypeData = m_aUIElements[nElementType];
195 
196     if ( !rElementTypeData.bLoaded )
197     {
198         Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
199         if ( xElementTypeStorage.is() )
200         {
201             rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE );
202             aBuf.appendAscii( RESOURCEURL_PREFIX );
203             aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] );
204             aBuf.appendAscii( "/" );
205             rtl::OUString aResURLPrefix( aBuf.makeStringAndClear() );
206 
207             UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap;
208             Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY );
209             Sequence< rtl::OUString > aUIElementNames = xNameAccess->getElementNames();
210             for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ )
211             {
212                 UIElementData aUIElementData;
213 
214                 // Resource name must be without ".xml"
215                 sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' );
216                 if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() ))
217                 {
218                     rtl::OUString aExtension( aUIElementNames[n].copy( nIndex+1 ));
219                     rtl::OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex ));
220 
221                     if (( aUIElementName.getLength() > 0 ) &&
222                         ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 )))
223                     {
224                         aUIElementData.aResourceURL = aResURLPrefix + aUIElementName;
225                         aUIElementData.aName        = aUIElementNames[n];
226                         aUIElementData.bModified    = false;
227                         aUIElementData.bDefault     = false;
228 
229                         // Create hash_map entries for all user interface elements inside the storage. We don't load the
230                         // settings to speed up the process.
231                         rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData ));
232                     }
233                 }
234             }
235         }
236     }
237 
238     rElementTypeData.bLoaded = true;
239 }
240 
241 void UIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, UIElementData& aUIElementData )
242 {
243     UIElementType& rElementTypeData = m_aUIElements[nElementType];
244 
245     Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
246     if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() )
247     {
248         try
249         {
250             Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ );
251             Reference< XInputStream > xInputStream = xStream->getInputStream();
252 
253             if ( xInputStream.is() )
254             {
255                 switch ( nElementType )
256                 {
257                     case ::com::sun::star::ui::UIElementType::UNKNOWN:
258                     break;
259 
260                     case ::com::sun::star::ui::UIElementType::MENUBAR:
261                     {
262                         try
263                         {
264                             MenuConfiguration aMenuCfg( m_xServiceManager );
265                             Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream ));
266                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer );
267                             if ( pRootItemContainer )
268                                 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
269                             else
270                                 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY );
271                             return;
272                         }
273                         catch ( ::com::sun::star::lang::WrappedTargetException& )
274                         {
275                         }
276                     }
277                     break;
278 
279                     case ::com::sun::star::ui::UIElementType::POPUPMENU:
280                     {
281                         break;
282                     }
283 
284                     case ::com::sun::star::ui::UIElementType::TOOLBAR:
285                     {
286                         try
287                         {
288                             Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
289                             ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer );
290                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
291                             aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
292                             return;
293                         }
294                         catch ( ::com::sun::star::lang::WrappedTargetException& )
295                         {
296                         }
297 
298                         break;
299                     }
300 
301                     case ::com::sun::star::ui::UIElementType::STATUSBAR:
302                     {
303                         try
304                         {
305                             Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
306                             StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer );
307                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
308                             aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
309                             return;
310                         }
311                         catch ( ::com::sun::star::lang::WrappedTargetException& )
312                         {
313                         }
314 
315                         break;
316                     }
317 
318                     case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW:
319                     {
320                         break;
321                     }
322                 }
323             }
324         }
325         catch ( ::com::sun::star::embed::InvalidStorageException& )
326         {
327         }
328 		catch (	::com::sun::star::lang::IllegalArgumentException& )
329         {
330         }
331         catch ( ::com::sun::star::io::IOException& )
332         {
333         }
334         catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
335         {
336         }
337     }
338 
339     // At least we provide an empty settings container!
340     aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer()), UNO_QUERY );
341 }
342 
343 UIConfigurationManager::UIElementData* UIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad )
344 {
345     // preload list of element types on demand
346     impl_preloadUIElementTypeList( nElementType );
347 
348     // try to look into our document vector/hash_map combination
349     UIElementDataHashMap& rUserHashMap = m_aUIElements[nElementType].aElementsHashMap;
350     UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL );
351     if ( pIter != rUserHashMap.end() )
352     {
353         // Default data settings data means removed!
354         if ( pIter->second.bDefault )
355             return &(pIter->second);
356         else
357         {
358             if ( !pIter->second.xSettings.is() && bLoad )
359                 impl_requestUIElementData( nElementType, pIter->second );
360             return &(pIter->second);
361         }
362     }
363 
364     // Nothing has been found!
365     return NULL;
366 }
367 
368 void UIConfigurationManager::impl_storeElementTypeData( Reference< XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState )
369 {
370     UIElementDataHashMap& rHashMap          = rElementType.aElementsHashMap;
371     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
372 
373     while ( pIter != rHashMap.end() )
374     {
375         UIElementData& rElement = pIter->second;
376         if ( rElement.bModified )
377         {
378             if ( rElement.bDefault )
379             {
380                 xStorage->removeElement( rElement.aName );
381                 rElement.bModified = sal_False; // mark as not modified
382             }
383             else
384             {
385                 Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY );
386                 Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
387 
388                 if ( xOutputStream.is() )
389                 {
390                     switch( rElementType.nElementType )
391                     {
392                         case ::com::sun::star::ui::UIElementType::MENUBAR:
393                         {
394                             try
395                             {
396                                 MenuConfiguration aMenuCfg( m_xServiceManager );
397                                 aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream );
398                             }
399                             catch ( ::com::sun::star::lang::WrappedTargetException& )
400                             {
401                             }
402                         }
403                         break;
404 
405                         case ::com::sun::star::ui::UIElementType::TOOLBAR:
406                         {
407                             try
408                             {
409                                 ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings );
410                             }
411                             catch ( ::com::sun::star::lang::WrappedTargetException& )
412                             {
413                             }
414                         }
415                         break;
416 
417                         case ::com::sun::star::ui::UIElementType::STATUSBAR:
418                         {
419                             try
420                             {
421                                 StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings );
422                             }
423                             catch ( ::com::sun::star::lang::WrappedTargetException& )
424                             {
425                             }
426                         }
427                         break;
428 
429                         default:
430                         break;
431                     }
432                 }
433 
434                 // mark as not modified if we store to our own storage
435                 if ( bResetModifyState )
436                     rElement.bModified = sal_False;
437             }
438         }
439 
440         ++pIter;
441     }
442 
443     // commit element type storage
444     Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY );
445 	if ( xTransactedObject.is() )
446     	xTransactedObject->commit();
447 
448     // mark UIElementType as not modified if we store to our own storage
449     if ( bResetModifyState )
450         rElementType.bModified = sal_False;
451 }
452 
453 void UIConfigurationManager::impl_resetElementTypeData(
454     UIElementType& rDocElementType,
455     ConfigEventNotifyContainer& rRemoveNotifyContainer )
456 {
457     UIElementDataHashMap& rHashMap          = rDocElementType.aElementsHashMap;
458     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
459 
460     Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
461     Reference< XInterface > xIfac( xThis, UNO_QUERY );
462 
463     // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
464     // our listeners!
465     while ( pIter != rHashMap.end() )
466     {
467         UIElementData& rElement = pIter->second;
468         if ( !rElement.bDefault )
469         {
470             // Remove user-defined settings from document
471             ConfigurationEvent aEvent;
472             aEvent.ResourceURL = rElement.aResourceURL;
473             aEvent.Accessor <<= xThis;
474             aEvent.Source = xIfac;
475             aEvent.Element <<= rElement.xSettings;
476 
477             rRemoveNotifyContainer.push_back( aEvent );
478 
479             // Mark element as default.
480             rElement.bModified = false;
481             rElement.bDefault  = true;
482         }
483         else
484             rElement.bModified = false;
485 
486         ++pIter;
487     }
488 
489     // Remove all settings from our user interface elements
490     rHashMap.clear();
491 }
492 
493 void UIConfigurationManager::impl_reloadElementTypeData(
494     UIElementType&              rDocElementType,
495     ConfigEventNotifyContainer& rRemoveNotifyContainer,
496     ConfigEventNotifyContainer& rReplaceNotifyContainer )
497 {
498     UIElementDataHashMap& rHashMap          = rDocElementType.aElementsHashMap;
499     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
500     Reference< XStorage > xElementStorage( rDocElementType.xStorage );
501     Reference< XNameAccess > xElementNameAccess( xElementStorage, UNO_QUERY );
502 
503     Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
504     Reference< XInterface > xIfac( xThis, UNO_QUERY );
505     sal_Int16 nType = rDocElementType.nElementType;
506 
507     while ( pIter != rHashMap.end() )
508     {
509         UIElementData& rElement = pIter->second;
510         if ( rElement.bModified )
511         {
512             if ( xElementNameAccess->hasByName( rElement.aName ))
513             {
514                 // Replace settings with data from user layer
515                 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
516 
517                 impl_requestUIElementData( nType, rElement );
518 
519                 ConfigurationEvent aReplaceEvent;
520 
521                 aReplaceEvent.ResourceURL = rElement.aResourceURL;
522                 aReplaceEvent.Accessor <<= xThis;
523                 aReplaceEvent.Source = xIfac;
524                 aReplaceEvent.ReplacedElement <<= xOldSettings;
525                 aReplaceEvent.Element <<= rElement.xSettings;
526                 rReplaceNotifyContainer.push_back( aReplaceEvent );
527 
528                 rElement.bModified = false;
529             }
530             else
531             {
532                 // Element settings are not in any storage => remove
533                 ConfigurationEvent aRemoveEvent;
534 
535                 aRemoveEvent.ResourceURL = rElement.aResourceURL;
536                 aRemoveEvent.Accessor <<= xThis;
537                 aRemoveEvent.Source = xIfac;
538                 aRemoveEvent.Element <<= rElement.xSettings;
539 
540                 rRemoveNotifyContainer.push_back( aRemoveEvent );
541 
542                 // Mark element as default and not modified. That means "not active" in the document anymore
543                 rElement.bModified = false;
544                 rElement.bDefault  = true;
545             }
546         }
547         ++pIter;
548     }
549 
550     rDocElementType.bModified = sal_False;
551 }
552 
553 void UIConfigurationManager::impl_Initialize()
554 {
555     // Initialize the top-level structures with the storage data
556     if ( m_xDocConfigStorage.is() )
557     {
558         long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE;
559 
560         // Try to access our module sub folder
561         for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
562               i++ )
563         {
564             Reference< XStorage > xElementTypeStorage;
565             try
566             {
567                 xElementTypeStorage = m_xDocConfigStorage->openStorageElement( rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), nModes );
568             }
569             catch ( com::sun::star::container::NoSuchElementException& )
570             {
571             }
572             catch ( ::com::sun::star::embed::InvalidStorageException& )
573             {
574             }
575             catch ( ::com::sun::star::lang::IllegalArgumentException& )
576             {
577             }
578             catch ( ::com::sun::star::io::IOException& )
579             {
580             }
581             catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
582             {
583             }
584 
585             m_aUIElements[i].nElementType = i;
586             m_aUIElements[i].bModified = false;
587             m_aUIElements[i].xStorage = xElementTypeStorage;
588             m_aUIElements[i].bDefaultLayer = false;
589         }
590     }
591     else
592     {
593         // We have no storage, just initialize ui element types with empty storage!
594         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
595             m_aUIElements[i].xStorage = m_xDocConfigStorage;
596     }
597 }
598 
599 UIConfigurationManager::UIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) :
600     ThreadHelpBase( &Application::GetSolarMutex() )
601     , m_xDocConfigStorage( 0 )
602     , m_bReadOnly( true )
603     , m_bInitialized( false )
604     , m_bModified( false )
605     , m_bConfigRead( false )
606     , m_bDisposed( false )
607     , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" ))
608     , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))
609     , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))
610     , m_xServiceManager( xServiceManager )
611     , m_aListenerContainer( m_aLock.getShareableOslMutex() )
612 {
613     // Make sure we have a default initialized entry for every layer and user interface element type!
614     // The following code depends on this!
615     m_aUIElements.resize( ::com::sun::star::ui::UIElementType::COUNT );
616 }
617 
618 UIConfigurationManager::~UIConfigurationManager()
619 {
620 }
621 
622 // XComponent
623 void SAL_CALL UIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException)
624 {
625     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
626 
627     css::lang::EventObject aEvent( xThis );
628     m_aListenerContainer.disposeAndClear( aEvent );
629 
630 	{
631 	    ResetableGuard aGuard( m_aLock );
632         try
633         {
634             if ( m_xImageManager.is() )
635                 m_xImageManager->dispose();
636         }
637         catch ( Exception& )
638         {
639         }
640 
641         m_xImageManager.clear();
642         m_aUIElements.clear();
643         m_xDocConfigStorage.clear();
644         m_bConfigRead = false;
645         m_bModified = false;
646         m_bDisposed = true;
647     }
648 }
649 
650 void SAL_CALL UIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
651 {
652     {
653         ResetableGuard aGuard( m_aLock );
654 
655 	    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
656         if ( m_bDisposed )
657             throw DisposedException();
658     }
659 
660     m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
661 }
662 
663 void SAL_CALL UIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
664 {
665     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
666     m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
667 }
668 
669 // XUIConfigurationManager
670 void SAL_CALL UIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
671 {
672     {
673         ResetableGuard aGuard( m_aLock );
674 
675         /* SAFE AREA ----------------------------------------------------------------------------------------------- */
676         if ( m_bDisposed )
677             throw DisposedException();
678     }
679 
680     m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
681 }
682 
683 void SAL_CALL UIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
684 {
685     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
686     m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
687 }
688 
689 
690 void SAL_CALL UIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException)
691 {
692     ResetableGuard aGuard( m_aLock );
693 
694     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
695     if ( m_bDisposed )
696         throw DisposedException();
697 
698     if ( isReadOnly() )
699         return;
700 
701     bool bResetStorage( false );
702     if ( m_xDocConfigStorage.is() )
703     {
704         try
705         {
706             // Remove all elements from our user-defined storage!
707             bool bCommit( false );
708             for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
709             {
710                 UIElementType&        rElementType = m_aUIElements[i];
711                 Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY );
712 
713                 if ( xSubStorage.is() )
714                 {
715                     bool bCommitSubStorage( false );
716                     Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY );
717                     Sequence< rtl::OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames();
718                     for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ )
719                     {
720                         xSubStorage->removeElement( aUIElementStreamNames[j] );
721                         bCommitSubStorage = true;
722                         bCommit = true;
723                     }
724 
725                     if ( bCommitSubStorage )
726                     {
727                         Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY );
728 						if ( xTransactedObject.is() )
729                         	xTransactedObject->commit();
730                     }
731                 }
732             }
733 
734             // Commit changes
735             if ( bCommit )
736             {
737                 Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY );
738                 if ( xTransactedObject.is() )
739                     xTransactedObject->commit();
740             }
741             bResetStorage = true;
742 
743             // remove settings from user defined layer and notify listener about removed settings data!
744             // Try to access our module sub folder
745             ConfigEventNotifyContainer aRemoveEventNotifyContainer;
746             for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ )
747             {
748                 UIElementType& rDocElementType = m_aUIElements[j];
749 
750                 impl_resetElementTypeData( rDocElementType, aRemoveEventNotifyContainer );
751                 rDocElementType.bModified = sal_False;
752             }
753 
754             m_bModified = sal_False;
755 
756             // Unlock mutex before notify our listeners
757             aGuard.unlock();
758 
759             // Notify our listeners
760             for ( sal_uInt32 k = 0; k < aRemoveEventNotifyContainer.size(); k++ )
761                 implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove );
762         }
763         catch ( ::com::sun::star::lang::IllegalArgumentException& )
764         {
765         }
766         catch ( ::com::sun::star::container::NoSuchElementException& )
767         {
768         }
769         catch ( ::com::sun::star::embed::InvalidStorageException& )
770         {
771         }
772         catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
773         {
774         }
775     }
776 }
777 
778 Sequence< Sequence< PropertyValue > > SAL_CALL UIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType )
779 throw ( IllegalArgumentException, RuntimeException )
780 {
781     if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
782         throw IllegalArgumentException();
783 
784     ResetableGuard aGuard( m_aLock );
785     if ( m_bDisposed )
786         throw DisposedException();
787 
788     Sequence< Sequence< PropertyValue > > aElementInfoSeq;
789     UIElementInfoHashMap aUIElementInfoCollection;
790 
791     if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN )
792     {
793         for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
794             impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) );
795     }
796     else
797         impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
798 
799     Sequence< PropertyValue > aUIElementInfo( 2 );
800     aUIElementInfo[0].Name = m_aPropResourceURL;
801     aUIElementInfo[1].Name = m_aPropUIName;
802 
803     aElementInfoSeq.realloc( aUIElementInfoCollection.size() );
804     UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin();
805 
806     sal_Int32 n = 0;
807     while ( pIter != aUIElementInfoCollection.end() )
808     {
809         aUIElementInfo[0].Value <<= pIter->second.aResourceURL;
810         aUIElementInfo[1].Value <<= pIter->second.aUIName;
811         aElementInfoSeq[n++] = aUIElementInfo;
812         ++pIter;
813     }
814 
815     return aElementInfoSeq;
816 }
817 
818 Reference< XIndexContainer > SAL_CALL UIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException)
819 {
820     ResetableGuard aGuard( m_aLock );
821 
822     if ( m_bDisposed )
823         throw DisposedException();
824 
825     // Creates an empty item container which can be filled from outside
826     return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer()), UNO_QUERY );
827 }
828 
829 sal_Bool SAL_CALL UIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL )
830 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
831 {
832     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
833 
834     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
835         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
836         throw IllegalArgumentException();
837     else
838     {
839         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
840         if ( pDataSettings && !pDataSettings->bDefault )
841             return sal_True;
842     }
843 
844     return sal_False;
845 }
846 
847 Reference< XIndexAccess > SAL_CALL UIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable )
848 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
849 {
850     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
851 
852     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
853         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
854         throw IllegalArgumentException();
855     else
856     {
857         ResetableGuard aGuard( m_aLock );
858 
859         if ( m_bDisposed )
860             throw DisposedException();
861 
862         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
863         if ( pDataSettings && !pDataSettings->bDefault )
864         {
865             // Create a copy of our data if someone wants to change the data.
866             if ( bWriteable )
867                 return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY );
868             else
869                 return pDataSettings->xSettings;
870         }
871     }
872 
873     throw NoSuchElementException();
874 }
875 
876 void SAL_CALL UIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData )
877 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException)
878 {
879     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
880 
881     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
882         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
883         throw IllegalArgumentException();
884     else if ( m_bReadOnly )
885         throw IllegalAccessException();
886     else
887     {
888         ResetableGuard aGuard( m_aLock );
889 
890         if ( m_bDisposed )
891             throw DisposedException();
892 
893         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
894         if ( pDataSettings && !pDataSettings->bDefault )
895         {
896             // we have a settings entry in our user-defined layer - replace
897             Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
898 
899             // Create a copy of the data if the container is not const
900             Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
901             if ( xReplace.is() )
902                 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
903             else
904                 pDataSettings->xSettings = aNewData;
905 
906             pDataSettings->bDefault  = false;
907             pDataSettings->bModified = true;
908             m_bModified = true;
909 
910             // Modify type container
911             UIElementType& rElementType = m_aUIElements[nElementType];
912             rElementType.bModified = true;
913 
914             Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
915 
916             // Create event to notify listener about replaced element settings
917             ConfigurationEvent aEvent;
918             Reference< XInterface > xIfac( xThis, UNO_QUERY );
919 
920             aEvent.ResourceURL = ResourceURL;
921             aEvent.Accessor <<= xThis;
922             aEvent.Source = xIfac;
923             aEvent.ReplacedElement <<= xOldSettings;
924             aEvent.Element <<= pDataSettings->xSettings;
925 
926             aGuard.unlock();
927 
928             implts_notifyContainerListener( aEvent, NotifyOp_Replace );
929         }
930         else
931             throw NoSuchElementException();
932     }
933 }
934 
935 void SAL_CALL UIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL )
936 throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException)
937 {
938     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
939 
940     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
941         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
942         throw IllegalArgumentException();
943     else if ( m_bReadOnly )
944         throw IllegalAccessException();
945     else
946     {
947         ResetableGuard aGuard( m_aLock );
948 
949         if ( m_bDisposed )
950             throw DisposedException();
951 
952         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
953         if ( pDataSettings )
954         {
955             // If element settings are default, we don't need to change anything!
956             if ( pDataSettings->bDefault )
957                 return;
958             else
959             {
960                 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
961                 pDataSettings->bDefault = true;
962 
963                 // check if this is a default layer node
964                 pDataSettings->bModified = true; // we have to remove this node from the user layer!
965                 pDataSettings->xSettings.clear();
966                 m_bModified = true; // user layer must be written
967 
968                 // Modify type container
969                 UIElementType& rElementType = m_aUIElements[nElementType];
970                 rElementType.bModified = true;
971 
972                 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
973                 Reference< XInterface > xIfac( xThis, UNO_QUERY );
974 
975                 // Create event to notify listener about removed element settings
976                 ConfigurationEvent aEvent;
977 
978                 aEvent.ResourceURL = ResourceURL;
979                 aEvent.Accessor <<= xThis;
980                 aEvent.Source = xIfac;
981                 aEvent.Element <<= xRemovedSettings;
982 
983                 aGuard.unlock();
984 
985                 implts_notifyContainerListener( aEvent, NotifyOp_Remove );
986             }
987         }
988         else
989             throw NoSuchElementException();
990     }
991 }
992 
993 void SAL_CALL UIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
994 throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException )
995 {
996     sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
997 
998     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
999         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1000         throw IllegalArgumentException();
1001     else if ( m_bReadOnly )
1002         throw IllegalAccessException();
1003     else
1004     {
1005         ResetableGuard aGuard( m_aLock );
1006 
1007         if ( m_bDisposed )
1008             throw DisposedException();
1009 
1010         bool           bInsertData( false );
1011         UIElementData  aUIElementData;
1012         UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1013 
1014         if ( pDataSettings && !pDataSettings->bDefault )
1015             throw ElementExistException();
1016 
1017         if ( !pDataSettings )
1018         {
1019             pDataSettings = &aUIElementData;
1020             bInsertData   = true;
1021         }
1022 
1023         {
1024             pDataSettings->bDefault     = false;
1025             pDataSettings->bModified    = true;
1026 
1027             // Create a copy of the data if the container is not const
1028             Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1029             if ( xReplace.is() )
1030                 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1031             else
1032                 pDataSettings->xSettings = aNewData;
1033 
1034             m_bModified = true;
1035 
1036             UIElementType& rElementType = m_aUIElements[nElementType];
1037             rElementType.bModified = true;
1038 
1039             if ( bInsertData )
1040             {
1041                 pDataSettings->aName        = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1042                 pDataSettings->aResourceURL = NewResourceURL;
1043 
1044                 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1045                 rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, *pDataSettings ));
1046             }
1047 
1048             Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1049             Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1050             Reference< XInterface > xIfac( xThis, UNO_QUERY );
1051 
1052             // Create event to notify listener about removed element settings
1053             ConfigurationEvent aEvent;
1054 
1055             aEvent.ResourceURL = NewResourceURL;
1056             aEvent.Accessor <<= xThis;
1057             aEvent.Source = xIfac;
1058             aEvent.Element <<= xInsertSettings;
1059 
1060             aGuard.unlock();
1061 
1062             implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1063         }
1064     }
1065 }
1066 
1067 Reference< XInterface > SAL_CALL UIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException)
1068 {
1069     if ( m_bDisposed )
1070         throw DisposedException();
1071 
1072     if ( !m_xImageManager.is() )
1073     {
1074         m_xImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ImageManager( m_xServiceManager )),
1075                                                          UNO_QUERY );
1076         Reference< XInitialization > xInit( m_xImageManager, UNO_QUERY );
1077 
1078         Sequence< Any > aPropSeq( 2 );
1079         PropertyValue aPropValue;
1080         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" ));
1081         aPropValue.Value = makeAny( m_xDocConfigStorage );
1082         aPropSeq[0] = makeAny( aPropValue );
1083         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" ));
1084         aPropValue.Value = makeAny( m_aModuleIdentifier );
1085         aPropSeq[1] = makeAny( aPropValue );
1086 
1087         xInit->initialize( aPropSeq );
1088     }
1089 
1090     return Reference< XInterface >( m_xImageManager, UNO_QUERY );
1091 }
1092 
1093 Reference< XInterface > SAL_CALL UIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException)
1094 {
1095     // SAFE ->
1096     ResetableGuard aGuard( m_aLock );
1097 
1098     if (m_xAccConfig.is())
1099         return m_xAccConfig;
1100 
1101     Reference< XMultiServiceFactory > xSMGR         = m_xServiceManager;
1102     Reference< XStorage >             xDocumentRoot = m_xDocConfigStorage;
1103 
1104     aGuard.unlock();
1105     // <- SAFE
1106 
1107     Reference< XInterface >      xAccConfig = xSMGR->createInstance(SERVICENAME_DOCUMENTACCELERATORCONFIGURATION);
1108     Reference< XInitialization > xInit      (xAccConfig, UNO_QUERY_THROW);
1109 
1110     PropertyValue aProp;
1111     aProp.Name    = ::rtl::OUString::createFromAscii("DocumentRoot");
1112     aProp.Value <<= xDocumentRoot;
1113 
1114     Sequence< Any > lArgs(1);
1115     lArgs[0] <<= aProp;
1116 
1117     xInit->initialize(lArgs);
1118 
1119     // SAFE ->
1120     aGuard.lock();
1121     m_xAccConfig = xAccConfig;
1122     aGuard.unlock();
1123     // <- SAFE
1124 
1125     return xAccConfig;
1126 }
1127 
1128 Reference< XInterface > SAL_CALL UIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException)
1129 {
1130     return Reference< XInterface >();
1131 }
1132 
1133 // XUIConfigurationStorage
1134 void SAL_CALL UIConfigurationManager::setStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::RuntimeException)
1135 {
1136     ResetableGuard aGuard( m_aLock );
1137 
1138     if ( m_bDisposed )
1139         throw DisposedException();
1140 
1141     if ( m_xDocConfigStorage.is() )
1142     {
1143         try
1144         {
1145             // Dispose old storage to be sure that it will be closed
1146             Reference< XComponent > xComponent( m_xDocConfigStorage, UNO_QUERY );
1147             if ( xComponent.is() )
1148                 xComponent->dispose();
1149         }
1150         catch ( Exception& )
1151         {
1152         }
1153     }
1154 
1155     // We store the new storage. Be careful it could be an empty reference!
1156     m_xDocConfigStorage = Storage;
1157     m_bReadOnly         = sal_True;
1158 
1159     Reference< XUIConfigurationStorage > xAccUpdate(m_xAccConfig, UNO_QUERY);
1160     if ( xAccUpdate.is() )
1161         xAccUpdate->setStorage( m_xDocConfigStorage );
1162 
1163     if ( m_xImageManager.is() )
1164     {
1165         ImageManager* pImageManager = (ImageManager*)m_xImageManager.get();
1166         if ( pImageManager )
1167             pImageManager->setStorage( m_xDocConfigStorage );
1168     }
1169 
1170     if ( m_xDocConfigStorage.is() )
1171     {
1172         Reference< XPropertySet > xPropSet( m_xDocConfigStorage, UNO_QUERY );
1173         if ( xPropSet.is() )
1174         {
1175             try
1176             {
1177                 long nOpenMode = 0;
1178                 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" )));
1179                 if ( a >>= nOpenMode )
1180                     m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
1181             }
1182             catch ( com::sun::star::beans::UnknownPropertyException& )
1183             {
1184             }
1185 			catch ( com::sun::star::lang::WrappedTargetException& )
1186             {
1187             }
1188         }
1189     }
1190 
1191     impl_Initialize();
1192 }
1193 
1194 sal_Bool SAL_CALL UIConfigurationManager::hasStorage() throw (::com::sun::star::uno::RuntimeException)
1195 {
1196     ResetableGuard aGuard( m_aLock );
1197 
1198     if ( m_bDisposed )
1199         throw DisposedException();
1200 
1201     return ( m_xDocConfigStorage.is() );
1202 }
1203 
1204 // XUIConfigurationPersistence
1205 void SAL_CALL UIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1206 {
1207     ResetableGuard aGuard( m_aLock );
1208 
1209     if ( m_bDisposed )
1210         throw DisposedException();
1211 
1212     if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1213     {
1214         // Try to access our module sub folder
1215         ConfigEventNotifyContainer aRemoveNotifyContainer;
1216         ConfigEventNotifyContainer aReplaceNotifyContainer;
1217         for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1218         {
1219             try
1220             {
1221                 UIElementType& rDocElementType = m_aUIElements[i];
1222                 if ( rDocElementType.bModified )
1223                     impl_reloadElementTypeData( rDocElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1224             }
1225             catch ( Exception& )
1226             {
1227                 throw IOException();
1228             }
1229         }
1230 
1231         m_bModified = sal_False;
1232 
1233         // Unlock mutex before notify our listeners
1234         aGuard.unlock();
1235 
1236         // Notify our listeners
1237         for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ )
1238             implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove );
1239         for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ )
1240             implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace );
1241     }
1242 }
1243 
1244 void SAL_CALL UIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1245 {
1246     ResetableGuard aGuard( m_aLock );
1247 
1248     if ( m_bDisposed )
1249         throw DisposedException();
1250 
1251     if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1252     {
1253         // Try to access our module sub folder
1254         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1255         {
1256             try
1257             {
1258                 UIElementType& rElementType = m_aUIElements[i];
1259                 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY );
1260 
1261                 if ( rElementType.bModified && xStorage.is() )
1262                     impl_storeElementTypeData( xStorage, rElementType );
1263             }
1264             catch ( Exception& )
1265             {
1266                 throw IOException();
1267             }
1268         }
1269 
1270         m_bModified = false;
1271         Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY );
1272 		if ( xTransactedObject.is() )
1273         	xTransactedObject->commit();
1274     }
1275 }
1276 
1277 void SAL_CALL UIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1278 {
1279     ResetableGuard aGuard( m_aLock );
1280 
1281     if ( m_bDisposed )
1282         throw DisposedException();
1283 
1284     if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1285     {
1286         // Try to access our module sub folder
1287         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1288         {
1289             try
1290             {
1291                 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1292                                                            rtl::OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE ));
1293                 UIElementType& rElementType = m_aUIElements[i];
1294 
1295                 if ( rElementType.bModified && xElementTypeStorage.is() )
1296                     impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1297             }
1298             catch ( Exception& )
1299             {
1300                 throw IOException();
1301             }
1302         }
1303 
1304         Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1305 		if ( xTransactedObject.is() )
1306         	xTransactedObject->commit();
1307     }
1308 }
1309 
1310 sal_Bool SAL_CALL UIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException)
1311 {
1312     ResetableGuard aGuard( m_aLock );
1313 
1314     return m_bModified;
1315 }
1316 
1317 sal_Bool SAL_CALL UIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException)
1318 {
1319     ResetableGuard aGuard( m_aLock );
1320 
1321     return m_bReadOnly;
1322 }
1323 
1324 void UIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1325 {
1326     ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) );
1327     if ( pContainer != NULL )
1328 	{
1329         ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1330         while ( pIterator.hasMoreElements() )
1331         {
1332             try
1333             {
1334                 switch ( eOp )
1335                 {
1336                     case NotifyOp_Replace:
1337                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent );
1338                         break;
1339                     case NotifyOp_Insert:
1340                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent );
1341                         break;
1342                     case NotifyOp_Remove:
1343                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent );
1344                         break;
1345                 }
1346             }
1347             catch( css::uno::RuntimeException& )
1348             {
1349                 pIterator.remove();
1350             }
1351         }
1352 	}
1353 }
1354 
1355 } // namespace framework
1356