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 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 #include "uielement/uicommanddescription.hxx"
35 #include <threadhelp/resetableguard.hxx>
36 #include "services.h"
37 
38 #include "properties.h"
39 
40 //_________________________________________________________________________________________________________________
41 //	interface includes
42 //_________________________________________________________________________________________________________________
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/container/XNameAccess.hpp>
46 #include <com/sun/star/container/XNameContainer.hpp>
47 #include <com/sun/star/container/XContainer.hpp>
48 
49 //_________________________________________________________________________________________________________________
50 //	includes of other projects
51 //_________________________________________________________________________________________________________________
52 #include <rtl/ustrbuf.hxx>
53 #include <cppuhelper/implbase2.hxx>
54 #include <unotools/configmgr.hxx>
55 #include <tools/string.hxx>
56 
57 #ifndef _VCL_MNEMONIC_HXX_
58 #include <vcl/mnemonic.hxx>
59 #endif
60 #include <comphelper/sequence.hxx>
61 #include <rtl/logfile.hxx>
62 
63 //_________________________________________________________________________________________________________________
64 //	Defines
65 //_________________________________________________________________________________________________________________
66 //
67 
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::container;
72 using namespace ::com::sun::star::frame;
73 
74 //_________________________________________________________________________________________________________________
75 //	Namespace
76 //_________________________________________________________________________________________________________________
77 //
78 
79 struct ModuleToCommands
80 {
81     const char* pModuleId;
82     const char* pCommands;
83 };
84 
85 static const char GENERIC_UICOMMANDS[]                  = "generic";
86 static const char COMMANDS[]                            = "Commands";
87 static const char CONFIGURATION_ROOT_ACCESS[]           = "/org.openoffice.Office.UI.";
88 static const char CONFIGURATION_CMD_ELEMENT_ACCESS[]    = "/UserInterface/Commands";
89 static const char CONFIGURATION_POP_ELEMENT_ACCESS[]    = "/UserInterface/Popups";
90 static const char CONFIGURATION_PROPERTY_LABEL[]        = "Label";
91 static const char CONFIGURATION_PROPERTY_CONTEXT_LABEL[] = "ContextLabel";
92 
93 // Property names of the resulting Property Set
94 static const char PROPSET_LABEL[]                       = "Label";
95 static const char PROPSET_NAME[]                        = "Name";
96 static const char PROPSET_POPUP[]                       = "Popup";
97 static const char PROPSET_PROPERTIES[]                  = "Properties";
98 
99 // Special resource URLs to retrieve additional information
100 static const char PRIVATE_RESOURCE_URL[]                = "private:";
101 
102 const sal_Int32   COMMAND_PROPERTY_IMAGE                = 1;
103 const sal_Int32   COMMAND_PROPERTY_ROTATE               = 2;
104 const sal_Int32   COMMAND_PROPERTY_MIRROR               = 4;
105 
106 namespace framework
107 {
108 
109 //*****************************************************************************************************************
110 //	Configuration access class for PopupMenuControllerFactory implementation
111 //*****************************************************************************************************************
112 
113 class ConfigurationAccess_UICommand : // Order is neccessary for right initialization!
114                                         private ThreadHelpBase                           ,
115                                         public  ::cppu::WeakImplHelper2<XNameAccess,XContainerListener>
116 {
117     public:
118                                   ConfigurationAccess_UICommand( const ::rtl::OUString& aModuleName, const Reference< XNameAccess >& xGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager );
119         virtual                   ~ConfigurationAccess_UICommand();
120 
121         // XNameAccess
122         virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
123             throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
124 
125         virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
126             throw (::com::sun::star::uno::RuntimeException);
127 
128         virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
129             throw (::com::sun::star::uno::RuntimeException);
130 
131         // XElementAccess
132         virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
133             throw (::com::sun::star::uno::RuntimeException);
134 
135         virtual sal_Bool SAL_CALL hasElements()
136             throw (::com::sun::star::uno::RuntimeException);
137 
138         // container.XContainerListener
139         virtual void SAL_CALL     elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException);
140         virtual void SAL_CALL     elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException);
141         virtual void SAL_CALL     elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException);
142 
143         // lang.XEventListener
144         virtual void SAL_CALL disposing( const EventObject& aEvent ) throw(RuntimeException);
145 
146     protected:
147         virtual ::com::sun::star::uno::Any SAL_CALL getByNameImpl( const ::rtl::OUString& aName );
148 
149         struct CmdToInfoMap
150         {
151             CmdToInfoMap() : bPopup( false ),
152                              bCommandNameCreated( false ),
153                              nProperties( 0 ) {}
154 
155             rtl::OUString       aLabel;
156             rtl::OUString       aContextLabel;
157             rtl::OUString       aCommandName;
158             bool                bPopup : 1,
159                                 bCommandNameCreated : 1;
160             sal_Int32           nProperties;
161         };
162 
163         Any                       getSequenceFromCache( const rtl::OUString& aCommandURL );
164         Any                       getInfoFromCommand( const rtl::OUString& rCommandURL );
165         void                      fillInfoFromResult( CmdToInfoMap& rCmdInfo, const rtl::OUString& aLabel );
166         Any                       getUILabelFromCommand( const rtl::OUString& rCommandURL );
167         Sequence< rtl::OUString > getAllCommands();
168         sal_Bool                  fillCache();
169         sal_Bool                  addGenericInfoToCache();
170         void                      impl_fill(const Reference< XNameAccess >& _xConfigAccess,sal_Bool _bPopup,
171                                                 std::vector< ::rtl::OUString >& aImageCommandVector,
172                                                 std::vector< ::rtl::OUString >& aImageRotateVector,
173                                                 std::vector< ::rtl::OUString >& aImageMirrorVector);
174 
175     private:
176         typedef ::std::hash_map< ::rtl::OUString,
177                                  CmdToInfoMap,
178                                  OUStringHashCode,
179                                  ::std::equal_to< ::rtl::OUString > > CommandToInfoCache;
180 
181         sal_Bool initializeConfigAccess();
182 
183         rtl::OUString                     m_aConfigCmdAccess;
184         rtl::OUString                     m_aConfigPopupAccess;
185         rtl::OUString                     m_aPropUILabel;
186         rtl::OUString                     m_aPropUIContextLabel;
187         rtl::OUString                     m_aPropLabel;
188         rtl::OUString                     m_aPropName;
189         rtl::OUString                     m_aPropPopup;
190         rtl::OUString                     m_aPropProperties;
191         rtl::OUString                     m_aBrandName;
192         rtl::OUString                     m_aXMLFileFormatVersion;
193         rtl::OUString                     m_aVersion;
194         rtl::OUString                     m_aExtension;
195         rtl::OUString                     m_aPrivateResourceURL;
196         Reference< XNameAccess >          m_xGenericUICommands;
197         Reference< XMultiServiceFactory > m_xServiceManager;
198         Reference< XMultiServiceFactory > m_xConfigProvider;
199         //Reference< XMultiServiceFactory > m_xConfigProviderPopups;
200         Reference< XNameAccess >          m_xConfigAccess;
201         Reference< XNameAccess >          m_xConfigAccessPopups;
202         Sequence< rtl::OUString >         m_aCommandImageList;
203         Sequence< rtl::OUString >         m_aCommandRotateImageList;
204         Sequence< rtl::OUString >         m_aCommandMirrorImageList;
205         CommandToInfoCache                m_aCmdInfoCache;
206         sal_Bool                          m_bConfigAccessInitialized;
207         sal_Bool                          m_bCacheFilled;
208         sal_Bool                          m_bGenericDataRetrieved;
209 };
210 
211 //*****************************************************************************************************************
212 //	XInterface, XTypeProvider
213 //*****************************************************************************************************************
214 ConfigurationAccess_UICommand::ConfigurationAccess_UICommand( const rtl::OUString& aModuleName, const Reference< XNameAccess >& rGenericUICommands, const Reference< XMultiServiceFactory >& rServiceManager ) :
215     ThreadHelpBase(),
216     m_aConfigCmdAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )),
217     m_aConfigPopupAccess( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_ROOT_ACCESS )),
218     m_aPropUILabel( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_LABEL )),
219     m_aPropUIContextLabel( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_PROPERTY_CONTEXT_LABEL )),
220     m_aPropLabel( RTL_CONSTASCII_USTRINGPARAM( PROPSET_LABEL )),
221     m_aPropName( RTL_CONSTASCII_USTRINGPARAM( PROPSET_NAME )),
222     m_aPropPopup( RTL_CONSTASCII_USTRINGPARAM( PROPSET_POPUP )),
223     m_aPropProperties( RTL_CONSTASCII_USTRINGPARAM( PROPSET_PROPERTIES )),
224     m_aPrivateResourceURL( RTL_CONSTASCII_USTRINGPARAM( PRIVATE_RESOURCE_URL )),
225     m_xGenericUICommands( rGenericUICommands ),
226     m_xServiceManager( rServiceManager ),
227     m_bConfigAccessInitialized( sal_False ),
228     m_bCacheFilled( sal_False ),
229     m_bGenericDataRetrieved( sal_False )
230 {
231     // Create configuration hierachical access name
232     m_aConfigCmdAccess += aModuleName;
233     m_aConfigCmdAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_CMD_ELEMENT_ACCESS ));
234 
235     m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY );
236 
237     m_aConfigPopupAccess += aModuleName;
238     m_aConfigPopupAccess += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIGURATION_POP_ELEMENT_ACCESS ));
239     //m_xConfigProviderPopups = Reference< XMultiServiceFactory >( rServiceManager->createInstance(SERVICENAME_CFGPROVIDER),UNO_QUERY );
240 
241     rtl::OUString aTmp;
242     ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ) >>= aTmp;
243     m_aBrandName = aTmp;
244 }
245 
246 ConfigurationAccess_UICommand::~ConfigurationAccess_UICommand()
247 {
248     // SAFE
249     ResetableGuard aLock( m_aLock );
250     Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
251     if ( xContainer.is() )
252         xContainer->removeContainerListener( this );
253     xContainer = Reference< XContainer >( m_xConfigAccessPopups, UNO_QUERY );
254     if ( xContainer.is() )
255         xContainer->removeContainerListener( this );
256 }
257 
258 
259 // XNameAccess
260 Any SAL_CALL ConfigurationAccess_UICommand::getByNameImpl( const ::rtl::OUString& rCommandURL )
261 {
262     static sal_Int32 nRequests  = 0;
263 
264     ResetableGuard aLock( m_aLock );
265     if ( !m_bConfigAccessInitialized )
266     {
267         initializeConfigAccess();
268         m_bConfigAccessInitialized = sal_True;
269         fillCache();
270     }
271 
272     if ( rCommandURL.indexOf( m_aPrivateResourceURL ) == 0 )
273     {
274         // special keys to retrieve information about a set of commands
275         // SAFE
276         addGenericInfoToCache();
277 
278         if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDIMAGELIST ))
279             return makeAny( m_aCommandImageList );
280         else if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDROTATEIMAGELIST ))
281             return makeAny( m_aCommandRotateImageList );
282         else if ( rCommandURL.equalsIgnoreAsciiCaseAscii( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDMIRRORIMAGELIST ))
283             return makeAny( m_aCommandMirrorImageList );
284         else
285             return Any();
286     }
287     else
288     {
289         // SAFE
290         ++nRequests;
291         return getInfoFromCommand( rCommandURL );
292     }
293 }
294 
295 Any SAL_CALL ConfigurationAccess_UICommand::getByName( const ::rtl::OUString& rCommandURL )
296 throw ( NoSuchElementException, WrappedTargetException, RuntimeException)
297 {
298 	Any aRet( getByNameImpl( rCommandURL ) );
299 	if( !aRet.hasValue() )
300 		throw NoSuchElementException();
301 
302 	return aRet;
303 }
304 
305 Sequence< ::rtl::OUString > SAL_CALL ConfigurationAccess_UICommand::getElementNames()
306 throw ( RuntimeException )
307 {
308     return getAllCommands();
309 }
310 
311 sal_Bool SAL_CALL ConfigurationAccess_UICommand::hasByName( const ::rtl::OUString& rCommandURL )
312 throw (::com::sun::star::uno::RuntimeException)
313 {
314     return getByNameImpl( rCommandURL ).hasValue();
315 }
316 
317 // XElementAccess
318 Type SAL_CALL ConfigurationAccess_UICommand::getElementType()
319 throw ( RuntimeException )
320 {
321     return( ::getCppuType( (const Sequence< PropertyValue >*)NULL ) );
322 }
323 
324 sal_Bool SAL_CALL ConfigurationAccess_UICommand::hasElements()
325 throw ( RuntimeException )
326 {
327     // There must are global commands!
328     return sal_True;
329 }
330 
331 void ConfigurationAccess_UICommand::fillInfoFromResult( CmdToInfoMap& rCmdInfo, const rtl::OUString& aLabel )
332 {
333     String rStr( aLabel );
334     if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND )
335         rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", m_aBrandName );
336     rCmdInfo.aLabel       = ::rtl::OUString( rStr );
337     rStr.EraseTrailingChars( '.' ); // Remove "..." from string
338     rCmdInfo.aCommandName = ::rtl::OUString( MnemonicGenerator::EraseAllMnemonicChars( rStr ));
339     rCmdInfo.bCommandNameCreated = sal_True;
340 }
341 
342 Any ConfigurationAccess_UICommand::getSequenceFromCache( const ::rtl::OUString& aCommandURL )
343 {
344     CommandToInfoCache::iterator pIter = m_aCmdInfoCache.find( aCommandURL );
345     if ( pIter != m_aCmdInfoCache.end() )
346     {
347         if ( !pIter->second.bCommandNameCreated )
348             fillInfoFromResult( pIter->second, pIter->second.aLabel );
349 
350         Sequence< PropertyValue > aPropSeq( 4 );
351         aPropSeq[0].Name  = m_aPropLabel;
352         aPropSeq[0].Value = pIter->second.aContextLabel.getLength() ?
353                 makeAny( pIter->second.aContextLabel ): makeAny( pIter->second.aLabel );
354         aPropSeq[1].Name  = m_aPropName;
355         aPropSeq[1].Value <<= pIter->second.aCommandName;
356         aPropSeq[2].Name  = m_aPropPopup;
357         aPropSeq[2].Value <<= pIter->second.bPopup;
358         aPropSeq[3].Name  = m_aPropProperties;
359         aPropSeq[3].Value <<= pIter->second.nProperties;
360         return makeAny( aPropSeq );
361     }
362 
363     return Any();
364 }
365 void ConfigurationAccess_UICommand::impl_fill(const Reference< XNameAccess >& _xConfigAccess,sal_Bool _bPopup,
366                                                 std::vector< ::rtl::OUString >& aImageCommandVector,
367                                                 std::vector< ::rtl::OUString >& aImageRotateVector,
368                                                 std::vector< ::rtl::OUString >& aImageMirrorVector)
369 {
370     if ( _xConfigAccess.is() )
371     {
372         Sequence< ::rtl::OUString> aNameSeq = _xConfigAccess->getElementNames();
373         const sal_Int32 nCount = aNameSeq.getLength();
374         for ( sal_Int32 i = 0; i < nCount; i++ )
375         {
376             try
377             {
378                 Reference< XNameAccess > xNameAccess(_xConfigAccess->getByName( aNameSeq[i] ),UNO_QUERY);
379                 if ( xNameAccess.is() )
380                 {
381                     CmdToInfoMap aCmdToInfo;
382 
383                     aCmdToInfo.bPopup = _bPopup;
384                     xNameAccess->getByName( m_aPropUILabel )        >>= aCmdToInfo.aLabel;
385                     xNameAccess->getByName( m_aPropUIContextLabel ) >>= aCmdToInfo.aContextLabel;
386                     xNameAccess->getByName( m_aPropProperties )     >>= aCmdToInfo.nProperties;
387 
388                     m_aCmdInfoCache.insert( CommandToInfoCache::value_type( aNameSeq[i], aCmdToInfo ));
389 
390                     if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_IMAGE )
391                         aImageCommandVector.push_back( aNameSeq[i] );
392                     if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_ROTATE )
393                         aImageRotateVector.push_back( aNameSeq[i] );
394                     if ( aCmdToInfo.nProperties & COMMAND_PROPERTY_MIRROR )
395                         aImageMirrorVector.push_back( aNameSeq[i] );
396                 }
397             }
398             catch ( com::sun::star::lang::WrappedTargetException& )
399             {
400             }
401             catch ( com::sun::star::container::NoSuchElementException& )
402             {
403             }
404         }
405     } // if ( m_xConfigAccessPopups.is() )
406 }
407 sal_Bool ConfigurationAccess_UICommand::fillCache()
408 {
409     RTL_LOGFILE_CONTEXT( aLog, "framework (cd100003) ::ConfigurationAccess_UICommand::fillCache" );
410 
411     if ( m_bCacheFilled )
412         return sal_True;
413 
414     std::vector< ::rtl::OUString > aImageCommandVector;
415     std::vector< ::rtl::OUString > aImageRotateVector;
416     std::vector< ::rtl::OUString > aImageMirrorVector;
417 
418     impl_fill(m_xConfigAccess,sal_False,aImageCommandVector,aImageRotateVector,aImageMirrorVector);
419     impl_fill(m_xConfigAccessPopups,sal_True,aImageCommandVector,aImageRotateVector,aImageMirrorVector);
420     // Create cached sequences for fast retrieving
421     m_aCommandImageList       = comphelper::containerToSequence( aImageCommandVector );
422     m_aCommandRotateImageList = comphelper::containerToSequence( aImageRotateVector );
423     m_aCommandMirrorImageList = comphelper::containerToSequence( aImageMirrorVector );
424 
425     m_bCacheFilled = sal_True;
426 
427     return sal_True;
428 }
429 
430 sal_Bool ConfigurationAccess_UICommand::addGenericInfoToCache()
431 {
432     if ( m_xGenericUICommands.is() && !m_bGenericDataRetrieved )
433     {
434         Sequence< rtl::OUString > aCommandNameSeq;
435         try
436         {
437             if ( m_xGenericUICommands->getByName(
438                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDROTATEIMAGELIST ))) >>= aCommandNameSeq )
439                 m_aCommandRotateImageList = comphelper::concatSequences< rtl::OUString >( m_aCommandRotateImageList, aCommandNameSeq );
440         }
441         catch ( RuntimeException& e )
442         {
443             throw e;
444         }
445         catch ( Exception& )
446         {
447         }
448 
449         try
450         {
451             if ( m_xGenericUICommands->getByName(
452                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( UICOMMANDDESCRIPTION_NAMEACCESS_COMMANDMIRRORIMAGELIST ))) >>= aCommandNameSeq )
453                 m_aCommandMirrorImageList = comphelper::concatSequences< rtl::OUString >( m_aCommandMirrorImageList, aCommandNameSeq );
454         }
455         catch ( RuntimeException& e )
456         {
457             throw e;
458         }
459         catch ( Exception& )
460         {
461         }
462 
463         m_bGenericDataRetrieved = sal_True;
464     }
465 
466     return sal_True;
467 }
468 
469 Any ConfigurationAccess_UICommand::getInfoFromCommand( const rtl::OUString& rCommandURL )
470 {
471     Any a;
472 
473     try
474     {
475         a = getSequenceFromCache( rCommandURL );
476         if ( !a.hasValue() )
477         {
478             // First try to ask our global commands configuration access. It also caches maybe
479             // we find the entry in its cache first.
480             if ( m_xGenericUICommands.is() && m_xGenericUICommands->hasByName( rCommandURL ) )
481             {
482                 try
483                 {
484                     return m_xGenericUICommands->getByName( rCommandURL );
485                 }
486                 catch ( com::sun::star::lang::WrappedTargetException& )
487                 {
488                 }
489                 catch ( com::sun::star::container::NoSuchElementException& )
490                 {
491                 }
492             }
493         }
494     }
495     catch( com::sun::star::container::NoSuchElementException& )
496     {
497     }
498     catch ( com::sun::star::lang::WrappedTargetException& )
499     {
500     }
501 
502     return a;
503 }
504 
505 Sequence< rtl::OUString > ConfigurationAccess_UICommand::getAllCommands()
506 {
507     // SAFE
508     ResetableGuard aLock( m_aLock );
509 
510     if ( !m_bConfigAccessInitialized )
511     {
512         initializeConfigAccess();
513         m_bConfigAccessInitialized = sal_True;
514         fillCache();
515     }
516 
517     if ( m_xConfigAccess.is() )
518     {
519         Reference< XNameAccess > xNameAccess;
520 
521         try
522         {
523             Sequence< ::rtl::OUString > aNameSeq = m_xConfigAccess->getElementNames();
524 
525             if ( m_xGenericUICommands.is() )
526             {
527                 // Create concat list of supported user interface commands of the module
528                 Sequence< ::rtl::OUString > aGenericNameSeq = m_xGenericUICommands->getElementNames();
529                 sal_uInt32 nCount1 = aNameSeq.getLength();
530                 sal_uInt32 nCount2 = aGenericNameSeq.getLength();
531 
532                 aNameSeq.realloc( nCount1 + nCount2 );
533                 ::rtl::OUString* pNameSeq = aNameSeq.getArray();
534                 const ::rtl::OUString* pGenericSeq = aGenericNameSeq.getConstArray();
535                 for ( sal_uInt32 i = 0; i < nCount2; i++ )
536                     pNameSeq[nCount1+i] = pGenericSeq[i];
537             }
538 
539             return aNameSeq;
540         }
541         catch( com::sun::star::container::NoSuchElementException& )
542         {
543         }
544         catch ( com::sun::star::lang::WrappedTargetException& )
545         {
546         }
547     }
548 
549     return Sequence< rtl::OUString >();
550 }
551 
552 sal_Bool ConfigurationAccess_UICommand::initializeConfigAccess()
553 {
554     Sequence< Any > aArgs( 1 );
555     PropertyValue   aPropValue;
556 
557     try
558     {
559         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
560         aPropValue.Value <<= m_aConfigCmdAccess;
561         aArgs[0] <<= aPropValue;
562 
563         m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY );
564         if ( m_xConfigAccess.is() )
565         {
566             // Add as container listener
567             Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
568             if ( xContainer.is() )
569                 xContainer->addContainerListener( this );
570         }
571 
572         aPropValue.Value <<= m_aConfigPopupAccess;
573         aArgs[0] <<= aPropValue;
574         m_xConfigAccessPopups = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ),UNO_QUERY );
575         if ( m_xConfigAccessPopups.is() )
576         {
577             // Add as container listener
578             Reference< XContainer > xContainer( m_xConfigAccessPopups, UNO_QUERY );
579             if ( xContainer.is() )
580                 xContainer->addContainerListener( this );
581         }
582 
583         return sal_True;
584     }
585     catch ( WrappedTargetException& )
586     {
587     }
588     catch ( Exception& )
589     {
590     }
591 
592     return sal_False;
593 }
594 
595 // container.XContainerListener
596 void SAL_CALL ConfigurationAccess_UICommand::elementInserted( const ContainerEvent& ) throw(RuntimeException)
597 {
598     ResetableGuard aLock( m_aLock );
599     m_bCacheFilled = sal_False;
600     fillCache();
601 }
602 
603 void SAL_CALL ConfigurationAccess_UICommand::elementRemoved( const ContainerEvent& ) throw(RuntimeException)
604 {
605     ResetableGuard aLock( m_aLock );
606     m_bCacheFilled = sal_False;
607     fillCache();
608 }
609 
610 void SAL_CALL ConfigurationAccess_UICommand::elementReplaced( const ContainerEvent& ) throw(RuntimeException)
611 {
612     ResetableGuard aLock( m_aLock );
613     m_bCacheFilled = sal_False;
614     fillCache();
615 }
616 
617 // lang.XEventListener
618 void SAL_CALL ConfigurationAccess_UICommand::disposing( const EventObject& aEvent ) throw(RuntimeException)
619 {
620     // SAFE
621     // remove our reference to the config access
622     ResetableGuard aLock( m_aLock );
623 
624     Reference< XInterface > xIfac1( aEvent.Source, UNO_QUERY );
625     Reference< XInterface > xIfac2( m_xConfigAccess, UNO_QUERY );
626     if ( xIfac1 == xIfac2 )
627         m_xConfigAccess.clear();
628     else
629     {
630         xIfac2 = Reference< XInterface >( m_xConfigAccessPopups, UNO_QUERY );
631         if ( xIfac1 == xIfac2 )
632             m_xConfigAccessPopups.clear();
633     }
634 }
635 
636 //*****************************************************************************************************************
637 //	XInterface, XTypeProvider, XServiceInfo
638 //*****************************************************************************************************************
639 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE  (   UICommandDescription				    ,
640                                             ::cppu::OWeakObject						,
641                                             SERVICENAME_UICOMMANDDESCRIPTION	    ,
642 											IMPLEMENTATIONNAME_UICOMMANDDESCRIPTION
643 										)
644 
645 DEFINE_INIT_SERVICE                     (   UICommandDescription, {} )
646 
647 UICommandDescription::UICommandDescription( const Reference< XMultiServiceFactory >& xServiceManager ) :
648     ThreadHelpBase(),
649     m_aPrivateResourceURL( RTL_CONSTASCII_USTRINGPARAM( PRIVATE_RESOURCE_URL )),
650     m_xServiceManager( xServiceManager )
651 {
652     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::UICommandDescription" );
653     Reference< XNameAccess > xEmpty;
654     rtl::OUString aGenericUICommand( ::rtl::OUString::createFromAscii( "GenericCommands" ));
655     m_xGenericUICommands = new ConfigurationAccess_UICommand( aGenericUICommand, xEmpty, xServiceManager );
656 
657     impl_fillElements("ooSetupFactoryCommandConfigRef");
658 
659     // insert generic commands
660     UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aGenericUICommand );
661     if ( pIter != m_aUICommandsHashMap.end() )
662         pIter->second = m_xGenericUICommands;
663 }
664 UICommandDescription::UICommandDescription( const Reference< XMultiServiceFactory >& xServiceManager,bool ) :
665     ThreadHelpBase(),
666     m_xServiceManager( xServiceManager )
667 {
668 }
669 UICommandDescription::~UICommandDescription()
670 {
671     ResetableGuard aLock( m_aLock );
672     m_aModuleToCommandFileMap.clear();
673     m_aUICommandsHashMap.clear();
674     m_xGenericUICommands.clear();
675 }
676 void UICommandDescription::impl_fillElements(const sal_Char* _pName)
677 {
678     m_xModuleManager.set( m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ),UNO_QUERY );
679     Reference< XNameAccess > xNameAccess( m_xModuleManager, UNO_QUERY_THROW );
680     Sequence< rtl::OUString > aElementNames = xNameAccess->getElementNames();
681     Sequence< PropertyValue > aSeq;
682     ::rtl::OUString                  aModuleIdentifier;
683 
684     for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ )
685     {
686         aModuleIdentifier = aElementNames[i];
687         if ( xNameAccess->getByName( aModuleIdentifier ) >>= aSeq )
688         {
689             ::rtl::OUString aCommandStr;
690             for ( sal_Int32 y = 0; y < aSeq.getLength(); y++ )
691             {
692                 if ( aSeq[y].Name.equalsAscii(_pName) )
693                 {
694                     aSeq[y].Value >>= aCommandStr;
695                     break;
696                 }
697             }
698 
699             // Create first mapping ModuleIdentifier ==> Command File
700             m_aModuleToCommandFileMap.insert( ModuleToCommandFileMap::value_type( aModuleIdentifier, aCommandStr ));
701 
702             // Create second mapping Command File ==> commands instance
703             UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aCommandStr );
704             if ( pIter == m_aUICommandsHashMap.end() )
705                 m_aUICommandsHashMap.insert( UICommandsHashMap::value_type( aCommandStr, Reference< XNameAccess >() ));
706         }
707     } // for ( sal_Int32 i = 0; i < aElementNames.getLength(); i++ )
708 }
709 Reference< XNameAccess > UICommandDescription::impl_createConfigAccess(const ::rtl::OUString& _sName)
710 {
711     return new ConfigurationAccess_UICommand( _sName,m_xGenericUICommands,m_xServiceManager );
712 }
713 
714 Any SAL_CALL UICommandDescription::getByName( const ::rtl::OUString& aName )
715 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
716 {
717     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getByName" );
718     Any a;
719 
720     ResetableGuard aLock( m_aLock );
721 
722     ModuleToCommandFileMap::const_iterator pM2CIter = m_aModuleToCommandFileMap.find( aName );
723     if ( pM2CIter != m_aModuleToCommandFileMap.end() )
724     {
725         ::rtl::OUString aCommandFile( pM2CIter->second );
726         UICommandsHashMap::iterator pIter = m_aUICommandsHashMap.find( aCommandFile );
727         if ( pIter != m_aUICommandsHashMap.end() )
728         {
729             if ( pIter->second.is() )
730                 a <<= pIter->second;
731             else
732             {
733                 Reference< XNameAccess > xUICommands;
734                 ConfigurationAccess_UICommand* pUICommands = new ConfigurationAccess_UICommand( aCommandFile,
735                                                                                                m_xGenericUICommands,
736                                                                                                m_xServiceManager );
737                 xUICommands = Reference< XNameAccess >( static_cast< cppu::OWeakObject* >( pUICommands ),UNO_QUERY );
738                 pIter->second = xUICommands;
739                 a <<= xUICommands;
740             }
741         }
742     }
743     else if ( m_aPrivateResourceURL.getLength() && aName.indexOf( m_aPrivateResourceURL ) == 0 )
744     {
745         // special keys to retrieve information about a set of commands
746         return m_xGenericUICommands->getByName( aName );
747     }
748     else
749     {
750         throw NoSuchElementException();
751     }
752 
753     return a;
754 }
755 
756 Sequence< ::rtl::OUString > SAL_CALL UICommandDescription::getElementNames()
757 throw (::com::sun::star::uno::RuntimeException)
758 {
759     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getElementNames" );
760     ResetableGuard aLock( m_aLock );
761 
762     Sequence< rtl::OUString > aSeq( m_aModuleToCommandFileMap.size() );
763 
764     sal_Int32 n = 0;
765     ModuleToCommandFileMap::const_iterator pIter = m_aModuleToCommandFileMap.begin();
766     while ( pIter != m_aModuleToCommandFileMap.end() )
767     {
768         aSeq[n] = pIter->first;
769         ++pIter;
770     }
771 
772     return aSeq;
773 }
774 
775 sal_Bool SAL_CALL UICommandDescription::hasByName( const ::rtl::OUString& aName )
776 throw (::com::sun::star::uno::RuntimeException)
777 {
778     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::hasByName" );
779     ResetableGuard aLock( m_aLock );
780 
781     ModuleToCommandFileMap::const_iterator pIter = m_aModuleToCommandFileMap.find( aName );
782     return ( pIter != m_aModuleToCommandFileMap.end() );
783 }
784 
785 // XElementAccess
786 Type SAL_CALL UICommandDescription::getElementType()
787 throw (::com::sun::star::uno::RuntimeException)
788 {
789     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::getElementType" );
790     return( ::getCppuType( (const Reference< XNameAccess >*)NULL ) );
791 }
792 
793 sal_Bool SAL_CALL UICommandDescription::hasElements()
794 throw (::com::sun::star::uno::RuntimeException)
795 {
796     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "UICommandDescription::hasElements" );
797     // generic UI commands are always available!
798     return sal_True;
799 }
800 
801 } // namespace framework
802 
803