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