1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 #include <uiconfiguration/moduleuiconfigurationmanager.hxx>
27 #include <threadhelp/resetableguard.hxx>
28 #include <services.h>
29 #include <uielement/constitemcontainer.hxx>
30 #include <uielement/rootitemcontainer.hxx>
31 #include <uielement/uielementtypenames.hxx>
32 #include <framework/menuconfiguration.hxx>
33 #include <framework/toolboxconfiguration.hxx>
34 
35 #ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_
36 #include <framework/statusbarconfiguration.hxx>
37 #endif
38 
39 //_________________________________________________________________________________________________________________
40 //	interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/ui/UIElementType.hpp>
43 #include <com/sun/star/ui/ConfigurationEvent.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/embed/ElementModes.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/io/XStream.hpp>
49 
50 //_________________________________________________________________________________________________________________
51 //	other includes
52 //_________________________________________________________________________________________________________________
53 
54 #include <vcl/svapp.hxx>
55 #include <rtl/ustrbuf.hxx>
56 #include <comphelper/sequenceashashmap.hxx>
57 
58 //_________________________________________________________________________________________________________________
59 //	namespaces
60 //_________________________________________________________________________________________________________________
61 
62 using rtl::OUString;
63 using namespace com::sun::star::uno;
64 using namespace com::sun::star::io;
65 using namespace com::sun::star::embed;
66 using namespace com::sun::star::lang;
67 using namespace com::sun::star::container;
68 using namespace com::sun::star::beans;
69 using namespace ::com::sun::star::ui;
70 
71 namespace framework
72 {
73 
74 //*****************************************************************************************************************
75 //	XInterface, XTypeProvider, XServiceInfo
76 //*****************************************************************************************************************
77 DEFINE_XINTERFACE_8                    (    ModuleUIConfigurationManager                                                    ,
78                                             OWeakObject                                                                     ,
79                                             DIRECT_INTERFACE( css::lang::XTypeProvider                                      ),
80                                             DIRECT_INTERFACE( css::lang::XServiceInfo                                       ),
81                                             DIRECT_INTERFACE( css::lang::XComponent                                         ),
82                                             DIRECT_INTERFACE( css::lang::XInitialization                                    ),
83 											DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration                  ),
84                                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager           ),
85 											DIRECT_INTERFACE( ::com::sun::star::ui::XModuleUIConfigurationManager     ),
86                                             DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence       )
87 										)
88 
89 DEFINE_XTYPEPROVIDER_8                  (   ModuleUIConfigurationManager                                ,
90                                             css::lang::XTypeProvider			                        ,
91                                             css::lang::XServiceInfo				                        ,
92                                             css::lang::XComponent                                       ,
93                                             css::lang::XInitialization                                  ,
94                                             ::com::sun::star::ui::XUIConfiguration                ,
95 											::com::sun::star::ui::XUIConfigurationManager         ,
96                                             ::com::sun::star::ui::XModuleUIConfigurationManager   ,
97                                             ::com::sun::star::ui::XUIConfigurationPersistence
98 										)
99 
100 DEFINE_XSERVICEINFO_MULTISERVICE        (   ModuleUIConfigurationManager                    ,
101                                             ::cppu::OWeakObject                             ,
102                                             SERVICENAME_MODULEUICONFIGURATIONMANAGER	    ,
103 											IMPLEMENTATIONNAME_MODULEUICONFIGURATIONMANAGER
104 										)
105 
106 DEFINE_INIT_SERVICE                     (   ModuleUIConfigurationManager, {} )
107 
108 
109 // important: The order and position of the elements must match the constant
110 // definition of "::com::sun::star::ui::UIElementType"
111 static const char* UIELEMENTTYPENAMES[] =
112 {
113     "",  // Dummy value for unknown!
114     UIELEMENTTYPE_MENUBAR_NAME,
115     UIELEMENTTYPE_POPUPMENU_NAME,
116     UIELEMENTTYPE_TOOLBAR_NAME,
117     UIELEMENTTYPE_STATUSBAR_NAME,
118     UIELEMENTTYPE_FLOATINGWINDOW_NAME,
119     UIELEMENTTYPE_PROGRESSBAR_NAME,
120     UIELEMENTTYPE_TOOLPANEL_NAME
121 };
122 
123 static const char       RESOURCEURL_PREFIX[] = "private:resource/";
124 static const sal_Int32  RESOURCEURL_PREFIX_SIZE = 17;
125 static const char       RESOURCEURL_CUSTOM_ELEMENT[] = "custom_";
126 
127 static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL )
128 {
129 
130     if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
131         ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
132     {
133         OUString    aTmpStr     = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE );
134         sal_Int32   nIndex      = aTmpStr.indexOf( '/' );
135         if (( nIndex > 0 ) &&  ( aTmpStr.getLength() > nIndex ))
136         {
137             OUString aTypeStr( aTmpStr.copy( 0, nIndex ));
138             for ( int i = 0; i < UIElementType::COUNT; i++ )
139             {
140                 if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] ))
141                     return sal_Int16( i );
142             }
143         }
144     }
145 
146     return UIElementType::UNKNOWN;
147 }
148 
149 static OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL )
150 {
151     if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
152         ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
153     {
154         sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' );
155         if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength()))
156             return aResourceURL.copy( nIndex+1 );
157     }
158 
159     return OUString();
160 }
161 
162 void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType )
163 {
164     // preload list of element types on demand
165     impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
166     impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
167 
168     UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
169     UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin();
170 
171     OUString aCustomUrlPrefix( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_CUSTOM_ELEMENT ));
172     while ( pUserIter != rUserElements.end() )
173     {
174         sal_Int32 nIndex = pUserIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE );
175         if ( nIndex > RESOURCEURL_PREFIX_SIZE )
176         {
177             // Performance: Retrieve user interface name only for custom user interface elements.
178             // It's only used by them!
179             UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType );
180             if ( pDataSettings )
181             {
182                 // Retrieve user interface name from XPropertySet interface
183                 rtl::OUString aUIName;
184                 Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
185                 if ( xPropSet.is() )
186                 {
187                     Any a = xPropSet->getPropertyValue( m_aPropUIName );
188                     a >>= aUIName;
189                 }
190 
191                 UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName );
192                 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
193             }
194         }
195         else
196         {
197             // The user interface name for standard user interface elements is stored in the WindowState.xcu file
198             UIElementInfo aInfo( pUserIter->second.aResourceURL, OUString() );
199             aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
200         }
201         ++pUserIter;
202     }
203 
204     UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
205     UIElementDataHashMap::const_iterator pDefIter = rDefaultElements.begin();
206 
207     while ( pDefIter != rDefaultElements.end() )
208     {
209         UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( pDefIter->second.aResourceURL );
210         if ( pIterInfo == aUIElementInfoCollection.end() )
211         {
212             sal_Int32 nIndex = pDefIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE );
213             if ( nIndex > RESOURCEURL_PREFIX_SIZE )
214             {
215                 // Performance: Retrieve user interface name only for custom user interface elements.
216                 // It's only used by them!
217                 UIElementData* pDataSettings = impl_findUIElementData( pDefIter->second.aResourceURL, nElementType );
218                 if ( pDataSettings )
219                 {
220                     // Retrieve user interface name from XPropertySet interface
221                     rtl::OUString aUIName;
222                     Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
223                     if ( xPropSet.is() )
224                     {
225                         Any a = xPropSet->getPropertyValue( m_aPropUIName );
226                         a >>= aUIName;
227                     }
228 
229                     UIElementInfo aInfo( pDefIter->second.aResourceURL, aUIName );
230                     aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo ));
231                 }
232             }
233             else
234             {
235                 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
236                 UIElementInfo aInfo( pDefIter->second.aResourceURL, OUString() );
237                 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo ));
238             }
239         }
240 
241         ++pDefIter;
242     }
243 }
244 
245 void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType )
246 {
247     UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
248 
249     if ( !rElementTypeData.bLoaded )
250     {
251         Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
252         if ( xElementTypeStorage.is() )
253         {
254             rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE );
255             aBuf.appendAscii( RESOURCEURL_PREFIX );
256             aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] );
257             aBuf.appendAscii( "/" );
258             OUString aResURLPrefix( aBuf.makeStringAndClear() );
259 
260             UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap;
261             Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY );
262             Sequence< OUString > aUIElementNames = xNameAccess->getElementNames();
263             for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ )
264             {
265                 UIElementData aUIElementData;
266 
267                 // Resource name must be without ".xml"
268                 sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' );
269                 if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() ))
270                 {
271                     OUString aExtension( aUIElementNames[n].copy( nIndex+1 ));
272                     OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex ));
273 
274                     if (( aUIElementName.getLength() > 0 ) &&
275                         ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 )))
276                     {
277                         aUIElementData.aResourceURL = aResURLPrefix + aUIElementName;
278                         aUIElementData.aName        = aUIElementNames[n];
279 
280                         if ( eLayer == LAYER_USERDEFINED )
281                         {
282                             aUIElementData.bModified    = false;
283                             aUIElementData.bDefault     = false;
284                             aUIElementData.bDefaultNode = false;
285                         }
286 
287                         // Create hash_map entries for all user interface elements inside the storage. We don't load the
288                         // settings to speed up the process.
289                         rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData ));
290                     }
291                 }
292 				rElementTypeData.bLoaded = true;
293             }
294         }
295     }
296 
297     //rElementTypeData.bLoaded = true;
298 }
299 
300 void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData )
301 {
302     UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
303 
304     Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
305     if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() )
306     {
307         try
308         {
309             Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ );
310             Reference< XInputStream > xInputStream = xStream->getInputStream();
311 
312             if ( xInputStream.is() )
313             {
314                 switch ( nElementType )
315                 {
316                     case ::com::sun::star::ui::UIElementType::UNKNOWN:
317                     break;
318 
319                     case ::com::sun::star::ui::UIElementType::MENUBAR:
320                     {
321                         try
322                         {
323                             MenuConfiguration aMenuCfg( m_xServiceManager );
324                             Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream ));
325                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer );
326                             if ( pRootItemContainer )
327                                 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
328                             else
329                                 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY );
330                             return;
331                         }
332                         catch ( ::com::sun::star::lang::WrappedTargetException& )
333                         {
334                         }
335                     }
336                     break;
337 
338                     case ::com::sun::star::ui::UIElementType::POPUPMENU:
339                     {
340                         break;
341                     }
342 
343                     case ::com::sun::star::ui::UIElementType::TOOLBAR:
344                     {
345                         try
346                         {
347                             Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
348                             ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer );
349                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
350                             aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
351                             return;
352                         }
353                         catch ( ::com::sun::star::lang::WrappedTargetException& )
354                         {
355                         }
356 
357                         break;
358                     }
359 
360                     case ::com::sun::star::ui::UIElementType::STATUSBAR:
361                     {
362                         try
363                         {
364                             Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
365                             StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer );
366                             RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
367                             aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
368                             return;
369                         }
370                         catch ( ::com::sun::star::lang::WrappedTargetException& )
371                         {
372                         }
373 
374                         break;
375                     }
376 
377                     case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW:
378                     {
379                         break;
380                     }
381                 }
382             }
383         }
384         catch ( ::com::sun::star::embed::InvalidStorageException& )
385         {
386         }
387 		catch (	::com::sun::star::lang::IllegalArgumentException& )
388         {
389         }
390         catch ( ::com::sun::star::io::IOException& )
391         {
392         }
393         catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
394         {
395         }
396     }
397 
398     // At least we provide an empty settings container!
399     aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer() ), UNO_QUERY );
400 }
401 
402 ModuleUIConfigurationManager::UIElementData*  ModuleUIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad )
403 {
404     // preload list of element types on demand
405     impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
406     impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
407 
408     // first try to look into our user-defined vector/hash_map combination
409     UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
410     UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL );
411     if ( pIter != rUserHashMap.end() )
412     {
413         // Default data settings data must be retrieved from the default layer!
414         if ( !pIter->second.bDefault )
415         {
416             if ( !pIter->second.xSettings.is() && bLoad )
417                 impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second );
418             return &(pIter->second);
419         }
420     }
421 
422     // Not successfull, we have to look into our default vector/hash_map combination
423     UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
424     pIter = rDefaultHashMap.find( aResourceURL );
425     if ( pIter != rDefaultHashMap.end() )
426     {
427         if ( !pIter->second.xSettings.is() && bLoad )
428             impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
429         return &(pIter->second);
430     }
431 
432     // Nothing has been found!
433     return NULL;
434 }
435 
436 void ModuleUIConfigurationManager::impl_storeElementTypeData( Reference< XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState )
437 {
438     UIElementDataHashMap& rHashMap          = rElementType.aElementsHashMap;
439     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
440 
441     while ( pIter != rHashMap.end() )
442     {
443         UIElementData& rElement = pIter->second;
444         if ( rElement.bModified )
445         {
446             if ( rElement.bDefault )
447             {
448                 xStorage->removeElement( rElement.aName );
449                 rElement.bModified = sal_False; // mark as not modified
450             }
451             else
452             {
453                 Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY );
454                 Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
455 
456                 if ( xOutputStream.is() )
457                 {
458                     switch( rElementType.nElementType )
459                     {
460                         case ::com::sun::star::ui::UIElementType::MENUBAR:
461                         {
462                             try
463                             {
464                                 MenuConfiguration aMenuCfg( m_xServiceManager );
465                                 aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream );
466                             }
467                             catch ( ::com::sun::star::lang::WrappedTargetException& )
468                             {
469                             }
470                         }
471                         break;
472 
473                         case ::com::sun::star::ui::UIElementType::TOOLBAR:
474                         {
475                             try
476                             {
477                                 ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings );
478                             }
479                             catch ( ::com::sun::star::lang::WrappedTargetException& )
480                             {
481                             }
482                         }
483                         break;
484 
485                         case ::com::sun::star::ui::UIElementType::STATUSBAR:
486                         {
487                             try
488                             {
489                                 StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings );
490                             }
491                             catch ( ::com::sun::star::lang::WrappedTargetException& )
492                             {
493                             }
494                         }
495                         break;
496 
497                         default:
498                         break;
499                     }
500                 }
501 
502                 // mark as not modified if we store to our own storage
503                 if ( bResetModifyState )
504                     rElement.bModified = sal_False;
505             }
506         }
507 
508         ++pIter;
509     }
510 
511     // commit element type storage
512     Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY );
513 	if ( xTransactedObject.is() )
514     	xTransactedObject->commit();
515 
516     // mark UIElementType as not modified if we store to our own storage
517     if ( bResetModifyState )
518         rElementType.bModified = sal_False;
519 }
520 
521 // This is only allowed to be called on the LAYER_USER_DEFINED!
522 void ModuleUIConfigurationManager::impl_resetElementTypeData(
523     UIElementType& rUserElementType,
524     UIElementType& rDefaultElementType,
525     ConfigEventNotifyContainer& rRemoveNotifyContainer,
526     ConfigEventNotifyContainer& rReplaceNotifyContainer )
527 {
528     UIElementDataHashMap& rHashMap          = rUserElementType.aElementsHashMap;
529     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
530 
531     Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
532     Reference< XInterface > xIfac( xThis, UNO_QUERY );
533     Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY );
534     sal_Int16 nType = rUserElementType.nElementType;
535 
536     // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
537     // our listeners!
538     while ( pIter != rHashMap.end() )
539     {
540         UIElementData& rElement = pIter->second;
541         if ( !rElement.bDefault )
542         {
543             if ( xDefaultNameAccess->hasByName( rElement.aName ))
544             {
545                 // Replace settings with data from default layer
546                 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
547                 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
548 
549                 ConfigurationEvent aReplaceEvent;
550                 aReplaceEvent.ResourceURL = rElement.aResourceURL;
551                 aReplaceEvent.Accessor <<= xThis;
552                 aReplaceEvent.Source = xIfac;
553                 aReplaceEvent.ReplacedElement <<= xOldSettings;
554                 aReplaceEvent.Element <<= rElement.xSettings;
555 
556                 rReplaceNotifyContainer.push_back( aReplaceEvent );
557 
558                 // Mark element as default and not modified. That means "not active"
559                 // in the user layer anymore.
560                 rElement.bModified = false;
561                 rElement.bDefault  = true;
562             }
563             else
564             {
565                 // Remove user-defined settings from user layer
566                 ConfigurationEvent aEvent;
567                 aEvent.ResourceURL = rElement.aResourceURL;
568                 aEvent.Accessor <<= xThis;
569                 aEvent.Source = xIfac;
570                 aEvent.Element <<= rElement.xSettings;
571 
572                 rRemoveNotifyContainer.push_back( aEvent );
573 
574                 // Mark element as default and not modified. That means "not active"
575                 // in the user layer anymore.
576                 rElement.bModified = false;
577                 rElement.bDefault  = true;
578             }
579         }
580 
581         ++pIter;
582     }
583 
584     // Remove all settings from our user interface elements
585     rHashMap.clear();
586 }
587 
588 void ModuleUIConfigurationManager::impl_reloadElementTypeData(
589     UIElementType&              rUserElementType,
590     UIElementType&              rDefaultElementType,
591     ConfigEventNotifyContainer& rRemoveNotifyContainer,
592     ConfigEventNotifyContainer& rReplaceNotifyContainer )
593 {
594     UIElementDataHashMap& rHashMap          = rUserElementType.aElementsHashMap;
595     UIElementDataHashMap::iterator pIter    = rHashMap.begin();
596     Reference< XStorage > xUserStorage( rUserElementType.xStorage );
597     Reference< XStorage > xDefaultStorage( rDefaultElementType.xStorage );
598     Reference< XNameAccess > xUserNameAccess( rUserElementType.xStorage, UNO_QUERY );
599     Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY );
600 
601     Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
602     Reference< XInterface > xIfac( xThis, UNO_QUERY );
603     sal_Int16 nType = rUserElementType.nElementType;
604 
605     while ( pIter != rHashMap.end() )
606     {
607         UIElementData& rElement = pIter->second;
608         if ( rElement.bModified )
609         {
610             if ( xUserNameAccess->hasByName( rElement.aName ))
611             {
612                 // Replace settings with data from user layer
613                 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
614 
615                 impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement );
616 
617                 ConfigurationEvent aReplaceEvent;
618 
619                 aReplaceEvent.ResourceURL = rElement.aResourceURL;
620                 aReplaceEvent.Accessor <<= xThis;
621                 aReplaceEvent.Source = xIfac;
622                 aReplaceEvent.ReplacedElement <<= xOldSettings;
623                 aReplaceEvent.Element <<= rElement.xSettings;
624                 rReplaceNotifyContainer.push_back( aReplaceEvent );
625 
626                 rElement.bModified = false;
627             }
628             else if ( xDefaultNameAccess->hasByName( rElement.aName ))
629             {
630                 // Replace settings with data from default layer
631                 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
632 
633                 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
634 
635                 ConfigurationEvent aReplaceEvent;
636 
637                 aReplaceEvent.ResourceURL = rElement.aResourceURL;
638                 aReplaceEvent.Accessor <<= xThis;
639                 aReplaceEvent.Source = xIfac;
640                 aReplaceEvent.ReplacedElement <<= xOldSettings;
641                 aReplaceEvent.Element <<= rElement.xSettings;
642                 rReplaceNotifyContainer.push_back( aReplaceEvent );
643 
644                 // Mark element as default and not modified. That means "not active"
645                 // in the user layer anymore.
646                 rElement.bModified = false;
647                 rElement.bDefault  = true;
648             }
649             else
650             {
651                 // Element settings are not in any storage => remove
652                 ConfigurationEvent aRemoveEvent;
653 
654                 aRemoveEvent.ResourceURL = rElement.aResourceURL;
655                 aRemoveEvent.Accessor <<= xThis;
656                 aRemoveEvent.Source = xIfac;
657                 aRemoveEvent.Element <<= rElement.xSettings;
658 
659                 rRemoveNotifyContainer.push_back( aRemoveEvent );
660 
661                 // Mark element as default and not modified. That means "not active"
662                 // in the user layer anymore.
663                 rElement.bModified = false;
664                 rElement.bDefault  = true;
665             }
666         }
667         ++pIter;
668     }
669 
670     rUserElementType.bModified = sal_False;
671 }
672 
673 void ModuleUIConfigurationManager::impl_Initialize()
674 {
675     // Initialize the top-level structures with the storage data
676     if ( m_xUserConfigStorage.is() )
677     {
678         // Try to access our module sub folder
679         for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
680               i++ )
681         {
682             Reference< XStorage > xElementTypeStorage;
683             try
684             {
685                 if ( m_pStorageHandler[i] )
686                     xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser();
687             }
688             catch ( com::sun::star::container::NoSuchElementException& )
689             {
690             }
691             catch ( ::com::sun::star::embed::InvalidStorageException& )
692             {
693             }
694             catch ( ::com::sun::star::lang::IllegalArgumentException& )
695             {
696             }
697             catch ( ::com::sun::star::io::IOException& )
698             {
699             }
700             catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
701             {
702             }
703 
704             m_aUIElements[LAYER_USERDEFINED][i].nElementType = i;
705             m_aUIElements[LAYER_USERDEFINED][i].bModified = false;
706             m_aUIElements[LAYER_USERDEFINED][i].xStorage = xElementTypeStorage;
707             m_aUIElements[LAYER_USERDEFINED][i].bDefaultLayer = false;
708         }
709     }
710 
711     if ( m_xDefaultConfigStorage.is() )
712     {
713         Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW );
714 
715         // Try to access our module sub folder
716         for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
717               i++ )
718         {
719             Reference< XStorage > xElementTypeStorage;
720             try
721             {
722 				const OUString sName( OUString::createFromAscii( UIELEMENTTYPENAMES[i] ) );
723 				if( xNameAccess->hasByName( sName ) )
724 	                xNameAccess->getByName( sName ) >>= xElementTypeStorage;
725             }
726             catch ( com::sun::star::container::NoSuchElementException& )
727             {
728             }
729 
730             m_aUIElements[LAYER_DEFAULT][i].nElementType = i;
731             m_aUIElements[LAYER_DEFAULT][i].bModified = false;
732             m_aUIElements[LAYER_DEFAULT][i].xStorage = xElementTypeStorage;
733             m_aUIElements[LAYER_DEFAULT][i].bDefaultLayer = true;
734         }
735     }
736 }
737 
738 ModuleUIConfigurationManager::ModuleUIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) :
739     ThreadHelpBase( &Application::GetSolarMutex() )
740     , m_xDefaultConfigStorage( 0 )
741     , m_xUserConfigStorage( 0 )
742     , m_bReadOnly( true )
743     , m_bInitialized( false )
744     , m_bModified( false )
745     , m_bConfigRead( false )
746     , m_bDisposed( false )
747     , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" ))
748     , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))
749     , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))
750     , m_xServiceManager( xServiceManager )
751     , m_aListenerContainer( m_aLock.getShareableOslMutex() )
752 {
753     for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
754         m_pStorageHandler[i] = 0;
755 
756     // Make sure we have a default initialized entry for every layer and user interface element type!
757     // The following code depends on this!
758     m_aUIElements[LAYER_DEFAULT].resize( ::com::sun::star::ui::UIElementType::COUNT );
759     m_aUIElements[LAYER_USERDEFINED].resize( ::com::sun::star::ui::UIElementType::COUNT );
760 }
761 
762 ModuleUIConfigurationManager::~ModuleUIConfigurationManager()
763 {
764     for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
765         delete m_pStorageHandler[i];
766 }
767 
768 // XComponent
769 void SAL_CALL ModuleUIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException)
770 {
771     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
772 
773     css::lang::EventObject aEvent( xThis );
774     m_aListenerContainer.disposeAndClear( aEvent );
775 
776     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
777     ResetableGuard aGuard( m_aLock );
778     Reference< XComponent > xModuleImageManager( m_xModuleImageManager );
779     m_xModuleImageManager.clear();
780     m_xModuleAcceleratorManager.clear();
781     m_aUIElements[LAYER_USERDEFINED].clear();
782     m_aUIElements[LAYER_DEFAULT].clear();
783     m_xDefaultConfigStorage.clear();
784     m_xUserConfigStorage.clear();
785     m_xUserRootCommit.clear();
786     m_bConfigRead = false;
787     m_bModified = false;
788     m_bDisposed = true;
789     aGuard.unlock();
790     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
791 
792     try
793     {
794         if ( xModuleImageManager.is() )
795             xModuleImageManager->dispose();
796     }
797     catch ( Exception& )
798     {
799     }
800 }
801 
802 void SAL_CALL ModuleUIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
803 {
804     {
805         ResetableGuard aGuard( m_aLock );
806 
807 	    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
808         if ( m_bDisposed )
809             throw DisposedException();
810     }
811 
812     m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
813 }
814 
815 void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
816 {
817     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
818     m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
819 }
820 
821 // XInitialization
822 void SAL_CALL ModuleUIConfigurationManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
823 {
824     ResetableGuard aLock( m_aLock );
825 
826     if ( !m_bInitialized )
827     {
828         ::comphelper::SequenceAsHashMap lArgs(aArguments);
829         m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString());
830         m_aModuleShortName  = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString());
831 
832         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
833         {
834             rtl::OUString aResourceType;
835             if ( i == ::com::sun::star::ui::UIElementType::MENUBAR )
836                 aResourceType = PresetHandler::RESOURCETYPE_MENUBAR();
837             else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR )
838                 aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR();
839             else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR )
840                 aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR();
841 
842             if ( aResourceType.getLength() > 0 )
843             {
844                 m_pStorageHandler[i] = new PresetHandler( m_xServiceManager );
845                 m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES,
846                                                          aResourceType, // this path wont be used later ... seee next lines!
847                                                          m_aModuleShortName,
848                                                          css::uno::Reference< css::embed::XStorage >()); // no document root used here!
849             }
850         }
851 
852         // initialize root storages for all resource types
853         m_xUserRootCommit       = css::uno::Reference< css::embed::XTransactedObject >(
854                                     m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty
855         m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare(
856                                     m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare());
857         m_xUserConfigStorage    = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser(
858                                     m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser());
859 
860         if ( m_xUserConfigStorage.is() )
861         {
862             Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY );
863             if ( xPropSet.is() )
864             {
865                 long nOpenMode = 0;
866                 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" )));
867                 if ( a >>= nOpenMode )
868                     m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
869             }
870         }
871 
872         impl_Initialize();
873 
874         m_bInitialized = true;
875     }
876 }
877 
878 // XUIConfiguration
879 void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
880 {
881     {
882         ResetableGuard aGuard( m_aLock );
883 
884         /* SAFE AREA ----------------------------------------------------------------------------------------------- */
885         if ( m_bDisposed )
886             throw DisposedException();
887     }
888 
889     m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
890 }
891 
892 void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
893 {
894     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
895     m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
896 }
897 
898 
899 // XUIConfigurationManager
900 void SAL_CALL ModuleUIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException)
901 {
902     ResetableGuard aGuard( m_aLock );
903 
904     /* SAFE AREA ----------------------------------------------------------------------------------------------- */
905     if ( m_bDisposed )
906         throw DisposedException();
907 
908     bool bResetStorage( false );
909 
910     if ( !isReadOnly() )
911     {
912         // Remove all elements from our user-defined storage!
913         try
914         {
915             for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
916             {
917                 UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
918                 Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY );
919 
920                 if ( xSubStorage.is() )
921                 {
922                     bool bCommitSubStorage( false );
923                     Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY );
924                     Sequence< OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames();
925                     for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ )
926                     {
927                         xSubStorage->removeElement( aUIElementStreamNames[j] );
928                         bCommitSubStorage = true;
929                     }
930 
931                     if ( bCommitSubStorage )
932                     {
933                         Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY );
934 						if ( xTransactedObject.is() )
935                         	xTransactedObject->commit();
936                         m_pStorageHandler[i]->commitUserChanges();
937                     }
938                 }
939             }
940 
941             bResetStorage = true;
942 
943             // remove settings from user defined layer and notify listener about removed settings data!
944             ConfigEventNotifyContainer aRemoveEventNotifyContainer;
945             ConfigEventNotifyContainer aReplaceEventNotifyContainer;
946             for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ )
947             {
948                 try
949                 {
950                     UIElementType& rUserElementType     = m_aUIElements[LAYER_USERDEFINED][j];
951                     UIElementType& rDefaultElementType  = m_aUIElements[LAYER_DEFAULT][j];
952 
953                     impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer );
954                     rUserElementType.bModified = sal_False;
955                 }
956                 catch ( Exception& )
957                 {
958                     throw IOException();
959                 }
960             }
961 
962             m_bModified = sal_False;
963 
964             // Unlock mutex before notify our listeners
965             aGuard.unlock();
966 
967             // Notify our listeners
968 		    sal_uInt32 k = 0;
969             for ( k = 0; k < aRemoveEventNotifyContainer.size(); k++ )
970                 implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove );
971             for ( k = 0; k < aReplaceEventNotifyContainer.size(); k++ )
972                 implts_notifyContainerListener( aReplaceEventNotifyContainer[k], NotifyOp_Replace );
973         }
974         catch ( ::com::sun::star::lang::IllegalArgumentException& )
975         {
976         }
977         catch ( ::com::sun::star::container::NoSuchElementException& )
978         {
979         }
980         catch ( ::com::sun::star::embed::InvalidStorageException& )
981         {
982         }
983         catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
984         {
985         }
986     }
987 }
988 
989 Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType )
990 throw ( IllegalArgumentException, RuntimeException )
991 {
992     if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
993         throw IllegalArgumentException();
994 
995     ResetableGuard aGuard( m_aLock );
996     if ( m_bDisposed )
997         throw DisposedException();
998 
999     Sequence< Sequence< PropertyValue > > aElementInfoSeq;
1000     UIElementInfoHashMap aUIElementInfoCollection;
1001 
1002     if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN )
1003     {
1004         for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1005             impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) );
1006     }
1007     else
1008         impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
1009 
1010     Sequence< PropertyValue > aUIElementInfo( 2 );
1011     aUIElementInfo[0].Name = m_aPropResourceURL;
1012     aUIElementInfo[1].Name = m_aPropUIName;
1013 
1014     aElementInfoSeq.realloc( aUIElementInfoCollection.size() );
1015     UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin();
1016 
1017     sal_Int32 n = 0;
1018     while ( pIter != aUIElementInfoCollection.end() )
1019     {
1020         aUIElementInfo[0].Value <<= pIter->second.aResourceURL;
1021         aUIElementInfo[1].Value <<= pIter->second.aUIName;
1022         aElementInfoSeq[n++] = aUIElementInfo;
1023         ++pIter;
1024     }
1025 
1026     return aElementInfoSeq;
1027 }
1028 
1029 Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException)
1030 {
1031     ResetableGuard aGuard( m_aLock );
1032 
1033     if ( m_bDisposed )
1034         throw DisposedException();
1035 
1036     // Creates an empty item container which can be filled from outside
1037     return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
1038 }
1039 
1040 sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL )
1041 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1042 {
1043     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1044 
1045     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1046         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1047         throw IllegalArgumentException();
1048     else
1049     {
1050         ResetableGuard aGuard( m_aLock );
1051 
1052         if ( m_bDisposed )
1053             throw DisposedException();
1054 
1055         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1056         if ( pDataSettings )
1057             return sal_True;
1058     }
1059 
1060     return sal_False;
1061 }
1062 
1063 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable )
1064 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1065 {
1066     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1067 
1068     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1069         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1070         throw IllegalArgumentException();
1071     else
1072     {
1073         ResetableGuard aGuard( m_aLock );
1074 
1075         if ( m_bDisposed )
1076             throw DisposedException();
1077 
1078         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1079         if ( pDataSettings )
1080         {
1081             // Create a copy of our data if someone wants to change the data.
1082             if ( bWriteable )
1083                 return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY );
1084             else
1085                 return pDataSettings->xSettings;
1086         }
1087     }
1088 
1089     throw NoSuchElementException();
1090 }
1091 
1092 void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData )
1093 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException)
1094 {
1095     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1096 
1097     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1098         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1099         throw IllegalArgumentException();
1100     else if ( m_bReadOnly )
1101         throw IllegalAccessException();
1102     else
1103     {
1104         ResetableGuard aGuard( m_aLock );
1105 
1106         if ( m_bDisposed )
1107             throw DisposedException();
1108 
1109         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1110         if ( pDataSettings )
1111         {
1112             if ( !pDataSettings->bDefaultNode )
1113             {
1114                 // we have a settings entry in our user-defined layer - replace
1115                 Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
1116 
1117                 // Create a copy of the data if the container is not const
1118                 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1119                 if ( xReplace.is() )
1120                     pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1121                 else
1122                     pDataSettings->xSettings = aNewData;
1123                 pDataSettings->bDefault  = false;
1124                 pDataSettings->bModified = true;
1125                 m_bModified = true;
1126 
1127                 // Modify type container
1128                 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1129                 rElementType.bModified = true;
1130 
1131                 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1132 
1133                 // Create event to notify listener about replaced element settings
1134                 ConfigurationEvent aEvent;
1135                 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1136 
1137                 aEvent.ResourceURL = ResourceURL;
1138                 aEvent.Accessor <<= xThis;
1139                 aEvent.Source = xIfac;
1140                 aEvent.ReplacedElement <<= xOldSettings;
1141                 aEvent.Element <<= pDataSettings->xSettings;
1142 
1143                 aGuard.unlock();
1144 
1145                 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1146             }
1147             else
1148             {
1149                 // we have no settings in our user-defined layer - insert
1150                 UIElementData aUIElementData;
1151 
1152                 aUIElementData.bDefault     = false;
1153                 aUIElementData.bDefaultNode = false;
1154                 aUIElementData.bModified    = true;
1155 
1156                 // Create a copy of the data if the container is not const
1157                 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1158                 if ( xReplace.is() )
1159                     aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1160                 else
1161                     aUIElementData.xSettings = aNewData;
1162                 aUIElementData.aName        = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix;
1163                 aUIElementData.aResourceURL = ResourceURL;
1164                 m_bModified = true;
1165 
1166                 // Modify type container
1167                 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1168                 rElementType.bModified = true;
1169 
1170                 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1171 
1172                 // Check our user element settings hash map as it can already contain settings that have been set to default!
1173                 // If no node can be found, we have to insert it.
1174                 UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL );
1175                 if ( pIter != rElements.end() )
1176                     pIter->second = aUIElementData;
1177                 else
1178                     rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData ));
1179 
1180                 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1181                 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1182 
1183                 // Create event to notify listener about replaced element settings
1184                 ConfigurationEvent aEvent;
1185 
1186                 aEvent.ResourceURL = ResourceURL;
1187                 aEvent.Accessor <<= xThis;
1188                 aEvent.Source = xIfac;
1189                 aEvent.ReplacedElement <<= pDataSettings->xSettings;
1190                 aEvent.Element <<= aUIElementData.xSettings;
1191 
1192                 aGuard.unlock();
1193 
1194                 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1195             }
1196         }
1197         else
1198             throw NoSuchElementException();
1199     }
1200 }
1201 
1202 void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL )
1203 throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException)
1204 {
1205     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1206 
1207     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1208         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1209         throw IllegalArgumentException();
1210     else if ( m_bReadOnly )
1211         throw IllegalAccessException();
1212     else
1213     {
1214         ResetableGuard aGuard( m_aLock );
1215 
1216         if ( m_bDisposed )
1217             throw DisposedException();
1218 
1219         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1220         if ( pDataSettings )
1221         {
1222             // If element settings are default, we don't need to change anything!
1223             if ( pDataSettings->bDefault )
1224                 return;
1225             else
1226             {
1227                 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
1228                 pDataSettings->bDefault = true;
1229 
1230                 // check if this is a default layer node
1231                 if ( !pDataSettings->bDefaultNode )
1232                     pDataSettings->bModified = true; // we have to remove this node from the user layer!
1233                 pDataSettings->xSettings.clear();
1234                 m_bModified = true; // user layer must be written
1235 
1236                 // Modify type container
1237                 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1238                 rElementType.bModified = true;
1239 
1240                 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1241                 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1242 
1243                 // Check if we have settings in the default layer which replaces the user-defined one!
1244                 UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1245                 if ( pDefaultDataSettings )
1246                 {
1247                     // Create event to notify listener about replaced element settings
1248                     ConfigurationEvent aEvent;
1249 
1250                     aEvent.ResourceURL = ResourceURL;
1251                     aEvent.Accessor <<= xThis;
1252                     aEvent.Source = xIfac;
1253                     aEvent.Element <<= xRemovedSettings;
1254                     aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings;
1255 
1256                     aGuard.unlock();
1257 
1258                     implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1259                 }
1260                 else
1261                 {
1262                     // Create event to notify listener about removed element settings
1263                     ConfigurationEvent aEvent;
1264 
1265                     aEvent.ResourceURL = ResourceURL;
1266                     aEvent.Accessor <<= xThis;
1267                     aEvent.Source = xIfac;
1268                     aEvent.Element <<= xRemovedSettings;
1269 
1270                     aGuard.unlock();
1271 
1272                     implts_notifyContainerListener( aEvent, NotifyOp_Remove );
1273                 }
1274             }
1275         }
1276         else
1277             throw NoSuchElementException();
1278     }
1279 }
1280 
1281 void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
1282 throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException )
1283 {
1284     sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
1285 
1286     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1287         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1288         throw IllegalArgumentException();
1289     else if ( m_bReadOnly )
1290         throw IllegalAccessException();
1291     else
1292     {
1293         ResetableGuard aGuard( m_aLock );
1294 
1295         if ( m_bDisposed )
1296             throw DisposedException();
1297 
1298         UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1299         if ( !pDataSettings )
1300         {
1301             UIElementData aUIElementData;
1302 
1303             aUIElementData.bDefault     = false;
1304             aUIElementData.bDefaultNode = false;
1305             aUIElementData.bModified    = true;
1306 
1307             // Create a copy of the data if the container is not const
1308             Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1309             if ( xReplace.is() )
1310                 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1311             else
1312                 aUIElementData.xSettings = aNewData;
1313             aUIElementData.aName        = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1314             aUIElementData.aResourceURL = NewResourceURL;
1315             m_bModified = true;
1316 
1317             UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1318             rElementType.bModified = true;
1319 
1320             UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1321             rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData ));
1322 
1323             Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1324             Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1325             Reference< XInterface > xIfac( xThis, UNO_QUERY );
1326 
1327             // Create event to notify listener about removed element settings
1328             ConfigurationEvent aEvent;
1329 
1330             aEvent.ResourceURL = NewResourceURL;
1331             aEvent.Accessor <<= xThis;
1332             aEvent.Source = xIfac;
1333             aEvent.Element <<= xInsertSettings;
1334 
1335             aGuard.unlock();
1336 
1337             implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1338         }
1339         else
1340             throw ElementExistException();
1341     }
1342 }
1343 
1344 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException)
1345 {
1346     ResetableGuard aGuard( m_aLock );
1347 
1348     if ( m_bDisposed )
1349         throw DisposedException();
1350 
1351     if ( !m_xModuleImageManager.is() )
1352     {
1353         m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )),
1354                                                          UNO_QUERY );
1355         Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY );
1356 
1357         Sequence< Any > aPropSeq( 3 );
1358         PropertyValue aPropValue;
1359         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" ));
1360         aPropValue.Value = makeAny( m_xUserConfigStorage );
1361         aPropSeq[0] = makeAny( aPropValue );
1362         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" ));
1363         aPropValue.Value = makeAny( m_aModuleIdentifier );
1364         aPropSeq[1] = makeAny( aPropValue );
1365         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" ));
1366         aPropValue.Value = makeAny( m_xUserRootCommit );
1367         aPropSeq[2] = makeAny( aPropValue );
1368 
1369         xInit->initialize( aPropSeq );
1370     }
1371 
1372     return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY );
1373 }
1374 
1375 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException)
1376 {
1377     ResetableGuard aGuard( m_aLock );
1378 
1379     if ( m_bDisposed )
1380         throw DisposedException();
1381 
1382     Reference< XMultiServiceFactory > xSMGR   = m_xServiceManager;
1383     ::rtl::OUString                   aModule = m_aModuleIdentifier;
1384 
1385     if ( !m_xModuleAcceleratorManager.is() )
1386     {
1387         Reference< XInterface >      xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION);
1388         Reference< XInitialization > xInit    (xManager, UNO_QUERY_THROW);
1389 
1390         PropertyValue aProp;
1391         aProp.Name    = ::rtl::OUString::createFromAscii("ModuleIdentifier");
1392         aProp.Value <<= aModule;
1393 
1394         Sequence< Any > lArgs(1);
1395         lArgs[0] <<= aProp;
1396 
1397         xInit->initialize(lArgs);
1398         m_xModuleAcceleratorManager = Reference< XInterface >( xManager, UNO_QUERY );
1399     }
1400 
1401     return m_xModuleAcceleratorManager;
1402 }
1403 
1404 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException)
1405 {
1406     return Reference< XInterface >();
1407 }
1408 
1409 // XModuleUIConfigurationManager
1410 sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL )
1411 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1412 {
1413     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1414 
1415     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1416         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1417         throw IllegalArgumentException();
1418     else
1419     {
1420         ResetableGuard aGuard( m_aLock );
1421 
1422         if ( m_bDisposed )
1423             throw DisposedException();
1424 
1425         UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1426         if ( pDataSettings && pDataSettings->bDefaultNode )
1427             return sal_True;
1428     }
1429 
1430     return sal_False;
1431 }
1432 
1433 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL )
1434 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1435 {
1436     sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1437 
1438     if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1439         ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT   ))
1440         throw IllegalArgumentException();
1441     else
1442     {
1443         ResetableGuard aGuard( m_aLock );
1444 
1445         if ( m_bDisposed )
1446             throw DisposedException();
1447 
1448         // preload list of element types on demand
1449         impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
1450 
1451         // Look into our default vector/hash_map combination
1452         UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
1453         UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL );
1454         if ( pIter != rDefaultHashMap.end() )
1455         {
1456             if ( !pIter->second.xSettings.is() )
1457                 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
1458             return pIter->second.xSettings;
1459         }
1460     }
1461 
1462     // Nothing has been found!
1463     throw NoSuchElementException();
1464 }
1465 
1466 // XUIConfigurationPersistence
1467 void SAL_CALL ModuleUIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1468 {
1469     ResetableGuard aGuard( m_aLock );
1470 
1471     if ( m_bDisposed )
1472         throw DisposedException();
1473 
1474     if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1475     {
1476         // Try to access our module sub folder
1477         ConfigEventNotifyContainer aRemoveNotifyContainer;
1478         ConfigEventNotifyContainer aReplaceNotifyContainer;
1479         for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1480         {
1481             try
1482             {
1483                 UIElementType& rUserElementType    = m_aUIElements[LAYER_USERDEFINED][i];
1484                 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i];
1485 
1486                 if ( rUserElementType.bModified )
1487                     impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1488             }
1489             catch ( Exception& )
1490             {
1491                 throw IOException();
1492             }
1493         }
1494 
1495         m_bModified = sal_False;
1496 
1497         // Unlock mutex before notify our listeners
1498         aGuard.unlock();
1499 
1500         // Notify our listeners
1501         for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ )
1502             implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove );
1503         for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ )
1504             implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace );
1505     }
1506 }
1507 
1508 void SAL_CALL ModuleUIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1509 {
1510     ResetableGuard aGuard( m_aLock );
1511 
1512     if ( m_bDisposed )
1513         throw DisposedException();
1514 
1515     if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1516     {
1517         // Try to access our module sub folder
1518         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1519         {
1520             try
1521             {
1522                 UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1523                 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY );
1524 
1525                 if ( rElementType.bModified && xStorage.is() )
1526                 {
1527                     impl_storeElementTypeData( xStorage, rElementType );
1528                     m_pStorageHandler[i]->commitUserChanges();
1529                 }
1530             }
1531             catch ( Exception& )
1532             {
1533                 throw IOException();
1534             }
1535         }
1536 
1537         m_bModified = false;
1538     }
1539 }
1540 
1541 void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1542 {
1543     ResetableGuard aGuard( m_aLock );
1544 
1545     if ( m_bDisposed )
1546         throw DisposedException();
1547 
1548     if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1549     {
1550         // Try to access our module sub folder
1551         for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1552         {
1553             try
1554             {
1555                 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1556                                                             OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE ));
1557                 UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1558 
1559                 if ( rElementType.bModified && xElementTypeStorage.is() )
1560                     impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1561             }
1562             catch ( Exception& )
1563             {
1564                 throw IOException();
1565             }
1566         }
1567 
1568         Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1569 		if ( xTransactedObject.is() )
1570         	xTransactedObject->commit();
1571     }
1572 }
1573 
1574 sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException)
1575 {
1576     ResetableGuard aGuard( m_aLock );
1577 
1578     return m_bModified;
1579 }
1580 
1581 sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException)
1582 {
1583     ResetableGuard aGuard( m_aLock );
1584 
1585     return m_bReadOnly;
1586 }
1587 
1588 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1589 {
1590     ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) );
1591     if ( pContainer != NULL )
1592 	{
1593         ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1594         while ( pIterator.hasMoreElements() )
1595         {
1596             try
1597             {
1598                 switch ( eOp )
1599                 {
1600                     case NotifyOp_Replace:
1601                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent );
1602                         break;
1603                     case NotifyOp_Insert:
1604                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent );
1605                         break;
1606                     case NotifyOp_Remove:
1607                         ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent );
1608                         break;
1609                 }
1610             }
1611             catch( css::uno::RuntimeException& )
1612             {
1613                 pIterator.remove();
1614             }
1615         }
1616 	}
1617 }
1618 
1619 } // namespace framework
1620