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 "uifactory/factoryconfiguration.hxx"
35 #include <threadhelp/resetableguard.hxx>
36 #include "services.h"
37 
38 //_________________________________________________________________________________________________________________
39 //	interface includes
40 //_________________________________________________________________________________________________________________
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/container/XNameContainer.hpp>
45 #include <com/sun/star/container/XContainer.hpp>
46 
47 //_________________________________________________________________________________________________________________
48 //	includes of other projects
49 //_________________________________________________________________________________________________________________
50 #include <rtl/ustrbuf.hxx>
51 #include <cppuhelper/weak.hxx>
52 #include <rtl/logfile.hxx>
53 
54 //_________________________________________________________________________________________________________________
55 //	Defines
56 //_________________________________________________________________________________________________________________
57 //
58 using namespace com::sun::star;
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::beans;
62 using namespace com::sun::star::container;
63 using namespace ::com::sun::star::frame;
64 
65 //_________________________________________________________________________________________________________________
66 //	Namespace
67 //_________________________________________________________________________________________________________________
68 //
69 
70 namespace framework
71 {
72 rtl::OUString getHashKeyFromStrings( const rtl::OUString& aCommandURL, const rtl::OUString& aModuleName )
73 {
74     rtl::OUStringBuffer aKey( aCommandURL );
75     aKey.appendAscii( "-" );
76     aKey.append( aModuleName );
77     return aKey.makeStringAndClear();
78 }
79 
80 //*****************************************************************************************************************
81 //	XInterface, XTypeProvider
82 //*****************************************************************************************************************
83 ConfigurationAccess_ControllerFactory::ConfigurationAccess_ControllerFactory( Reference< XMultiServiceFactory >& rServiceManager,const ::rtl::OUString& _sRoot,bool _bAskValue ) :
84     ThreadHelpBase(),
85     m_aPropCommand( RTL_CONSTASCII_USTRINGPARAM( "Command" )),
86     m_aPropModule( RTL_CONSTASCII_USTRINGPARAM( "Module" )),
87     m_aPropController( RTL_CONSTASCII_USTRINGPARAM( "Controller" )),
88     m_aPropValue( RTL_CONSTASCII_USTRINGPARAM( "Value" )),
89     m_sRoot(_sRoot),
90     m_xServiceManager( rServiceManager ),
91     m_bConfigAccessInitialized( sal_False ),
92     m_bAskValue(_bAskValue)
93 {
94     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::ConfigurationAccess_ControllerFactory" );
95     m_xConfigProvider = Reference< XMultiServiceFactory >( rServiceManager->createInstance( SERVICENAME_CFGPROVIDER),UNO_QUERY );
96 }
97 
98 ConfigurationAccess_ControllerFactory::~ConfigurationAccess_ControllerFactory()
99 {
100     // SAFE
101     ResetableGuard aLock( m_aLock );
102 
103     Reference< XContainer > xContainer( m_xConfigAccess, UNO_QUERY );
104     if ( xContainer.is() )
105         xContainer->removeContainerListener( this );
106 }
107 
108 rtl::OUString ConfigurationAccess_ControllerFactory::getServiceFromCommandModule( const rtl::OUString& rCommandURL, const rtl::OUString& rModule ) const
109 {
110     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::getServiceFromCommandModule" );
111     // SAFE
112     ResetableGuard aLock( m_aLock );
113     MenuControllerMap::const_iterator pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rModule ));
114 
115     if ( pIter != m_aMenuControllerMap.end() )
116         return pIter->second.m_aImplementationName;
117     else if ( rModule.getLength() )
118     {
119         // Try to detect if we have a generic popup menu controller
120         pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rtl::OUString() ));
121 
122         if ( pIter != m_aMenuControllerMap.end() )
123             return pIter->second.m_aImplementationName;
124     }
125 
126     return rtl::OUString();
127 }
128 rtl::OUString ConfigurationAccess_ControllerFactory::getValueFromCommandModule( const rtl::OUString& rCommandURL, const rtl::OUString& rModule ) const
129 {
130     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::getValueFromCommandModule" );
131     // SAFE
132     ResetableGuard aLock( m_aLock );
133 
134     MenuControllerMap::const_iterator pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rModule ));
135 
136     if ( pIter != m_aMenuControllerMap.end() )
137         return pIter->second.m_aValue;
138     else if ( rModule.getLength() )
139     {
140         // Try to detect if we have a generic popup menu controller
141         pIter = m_aMenuControllerMap.find( getHashKeyFromStrings( rCommandURL, rtl::OUString() ));
142 
143         if ( pIter != m_aMenuControllerMap.end() )
144             return pIter->second.m_aValue;
145     }
146 
147     return rtl::OUString();
148 }
149 
150 
151 void ConfigurationAccess_ControllerFactory::addServiceToCommandModule(
152     const rtl::OUString& rCommandURL,
153     const rtl::OUString& rModule,
154     const rtl::OUString& rServiceSpecifier )
155 {
156     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::addServiceToCommandModule" );
157     // SAFE
158     ResetableGuard aLock( m_aLock );
159 
160     rtl::OUString aHashKey = getHashKeyFromStrings( rCommandURL, rModule );
161     m_aMenuControllerMap.insert( MenuControllerMap::value_type( aHashKey,ControllerInfo(rServiceSpecifier,::rtl::OUString()) ));
162 }
163 
164 void ConfigurationAccess_ControllerFactory::removeServiceFromCommandModule(
165     const rtl::OUString& rCommandURL,
166     const rtl::OUString& rModule )
167 {
168     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::removeServiceFromCommandModule" );
169     // SAFE
170     ResetableGuard aLock( m_aLock );
171 
172     rtl::OUString aHashKey = getHashKeyFromStrings( rCommandURL, rModule );
173     m_aMenuControllerMap.erase( aHashKey );
174 }
175 
176 // container.XContainerListener
177 void SAL_CALL ConfigurationAccess_ControllerFactory::elementInserted( const ContainerEvent& aEvent ) throw(RuntimeException)
178 {
179     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::elementInserted" );
180     rtl::OUString   aCommand;
181     rtl::OUString   aModule;
182     rtl::OUString   aService;
183     rtl::OUString   aValue;
184 
185     // SAFE
186     ResetableGuard aLock( m_aLock );
187 
188     if ( impl_getElementProps( aEvent.Element, aCommand, aModule, aService, aValue ))
189     {
190         // Create hash key from command and module as they are together a primary key to
191         // the UNO service that implements the popup menu controller.
192         rtl::OUString aHashKey( getHashKeyFromStrings( aCommand, aModule ));
193         ControllerInfo& rControllerInfo = m_aMenuControllerMap[ aHashKey ];
194         rControllerInfo.m_aImplementationName = aService;
195         rControllerInfo.m_aValue = aValue;
196     }
197 }
198 
199 void SAL_CALL ConfigurationAccess_ControllerFactory::elementRemoved ( const ContainerEvent& aEvent ) throw(RuntimeException)
200 {
201     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::elementRemoved" );
202     rtl::OUString   aCommand;
203     rtl::OUString   aModule;
204     rtl::OUString   aService;
205     rtl::OUString   aValue;
206 
207     // SAFE
208     ResetableGuard aLock( m_aLock );
209 
210     if ( impl_getElementProps( aEvent.Element, aCommand, aModule, aService, aValue ))
211     {
212         // Create hash key from command and module as they are together a primary key to
213         // the UNO service that implements the popup menu controller.
214         rtl::OUString aHashKey( getHashKeyFromStrings( aCommand, aModule ));
215         m_aMenuControllerMap.erase( aHashKey );
216     }
217 }
218 
219 void SAL_CALL ConfigurationAccess_ControllerFactory::elementReplaced( const ContainerEvent& aEvent ) throw(RuntimeException)
220 {
221     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::elementReplaced" );
222     elementInserted(aEvent);
223 }
224 
225 // lang.XEventListener
226 void SAL_CALL ConfigurationAccess_ControllerFactory::disposing( const EventObject& ) throw(RuntimeException)
227 {
228     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::disposing" );
229     // SAFE
230     // remove our reference to the config access
231     ResetableGuard aLock( m_aLock );
232     m_xConfigAccess.clear();
233 }
234 
235 void ConfigurationAccess_ControllerFactory::readConfigurationData()
236 {
237     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::readConfigurationData" );
238     // SAFE
239     ResetableGuard aLock( m_aLock );
240 
241     if ( !m_bConfigAccessInitialized )
242     {
243         Sequence< Any > aArgs( 1 );
244         PropertyValue   aPropValue;
245 
246         aPropValue.Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ));
247         aPropValue.Value <<= m_sRoot;
248         aArgs[0] <<= aPropValue;
249 
250         try
251         {
252             m_xConfigAccess = Reference< XNameAccess >( m_xConfigProvider->createInstanceWithArguments(SERVICENAME_CFGREADACCESS,aArgs ), UNO_QUERY );
253         }
254         catch ( WrappedTargetException& )
255         {
256         }
257 
258         m_bConfigAccessInitialized = sal_True;
259     }
260 
261     if ( m_xConfigAccess.is() )
262     {
263         // Read and update configuration data
264         updateConfigurationData();
265 
266         uno::Reference< container::XContainer > xContainer( m_xConfigAccess, uno::UNO_QUERY );
267         // UNSAFE
268         aLock.unlock();
269 
270         if ( xContainer.is() )
271             xContainer->addContainerListener( this );
272     }
273 }
274 
275 void ConfigurationAccess_ControllerFactory::updateConfigurationData()
276 {
277     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::updateConfigurationData" );
278     // SAFE
279     ResetableGuard aLock( m_aLock );
280     if ( m_xConfigAccess.is() )
281     {
282         Sequence< rtl::OUString >   aPopupMenuControllers = m_xConfigAccess->getElementNames();
283 
284         rtl::OUString aCommand;
285         rtl::OUString aModule;
286         rtl::OUString aService;
287         rtl::OUString aHashKey;
288         rtl::OUString aValue;
289 
290         m_aMenuControllerMap.clear();
291         for ( sal_Int32 i = 0; i < aPopupMenuControllers.getLength(); i++ )
292         {
293             try
294             {
295                 if ( impl_getElementProps( m_xConfigAccess->getByName( aPopupMenuControllers[i] ), aCommand, aModule, aService,aValue ))
296                 {
297                     // Create hash key from command and module as they are together a primary key to
298                     // the UNO service that implements the popup menu controller.
299                     aHashKey = getHashKeyFromStrings( aCommand, aModule );
300                     m_aMenuControllerMap.insert( MenuControllerMap::value_type( aHashKey, ControllerInfo(aService,aValue) ));
301                 }
302             }
303             catch ( NoSuchElementException& )
304             {
305             }
306             catch ( WrappedTargetException& )
307             {
308             }
309         }
310     }
311 }
312 
313 sal_Bool ConfigurationAccess_ControllerFactory::impl_getElementProps( const Any& aElement, rtl::OUString& aCommand, rtl::OUString& aModule, rtl::OUString& aServiceSpecifier,rtl::OUString& aValue  ) const
314 {
315     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "framework", "Ocke.Janssen@sun.com", "ConfigurationAccess_ControllerFactory::impl_getElementProps" );
316     Reference< XPropertySet > xPropertySet;
317     aElement >>= xPropertySet;
318 
319     if ( xPropertySet.is() )
320     {
321         try
322         {
323             xPropertySet->getPropertyValue( m_aPropCommand ) >>= aCommand;
324             xPropertySet->getPropertyValue( m_aPropModule ) >>= aModule;
325             xPropertySet->getPropertyValue( m_aPropController ) >>= aServiceSpecifier;
326             if ( m_bAskValue )
327                 xPropertySet->getPropertyValue( m_aPropValue ) >>= aValue;
328         }
329         catch ( com::sun::star::beans::UnknownPropertyException& )
330         {
331             return sal_False;
332         }
333         catch ( com::sun::star::lang::WrappedTargetException& )
334         {
335             return sal_False;
336         }
337     }
338 
339     return sal_True;
340 }
341 } // namespace framework
342