xref: /AOO41X/main/unotools/source/config/inetoptions.cxx (revision cbe4a5e32dd06077057875dd5ecd4d8f1991662a)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_unotools.hxx"
26 #include <unotools/inetoptions.hxx>
27 #include "rtl/instance.hxx"
28 #include <tools/urlobj.hxx>
29 #ifndef _WILDCARD_HXX
30 #include <tools/wldcrd.hxx>
31 #endif
32 
33 #include <algorithm>
34 #include <map>
35 #include <set>
36 #include <vector>
37 #include <utility>
38 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
39 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/uno/Any.hxx>
42 #include <com/sun/star/uno/Exception.hpp>
43 #include <com/sun/star/uno/Reference.hxx>
44 #include <com/sun/star/uno/RuntimeException.hpp>
45 #include <osl/mutex.hxx>
46 #include <rtl/ustring.h>
47 #include <rtl/ustring.hxx>
48 #include <sal/types.h>
49 #include <unotools/configitem.hxx>
50 #include <unotools/processfactory.hxx>
51 #include <osl/diagnose.h>
52 #include <salhelper/refobj.hxx>
53 #include <rtl/logfile.hxx>
54 #include "itemholder1.hxx"
55 
56 using namespace com::sun;
57 
58 //============================================================================
59 //
60 //  takeAny
61 //
62 //============================================================================
63 
64 namespace {
65 
takeAny(star::uno::Any const & rAny)66 template< typename T > inline T takeAny(star::uno::Any const & rAny)
67 {
68     T aValue = T();
69     rAny >>= aValue;
70     return aValue;
71 }
72 
73 }
74 
75 //============================================================================
76 //
77 //  SvtInetOptions::Impl
78 //
79 //============================================================================
80 
81 class SvtInetOptions::Impl: public salhelper::ReferenceObject,
82                             public utl::ConfigItem
83 {
84 public:
85     enum Index
86     {
87         INDEX_NO_PROXY,
88         INDEX_PROXY_TYPE,
89         INDEX_FTP_PROXY_NAME,
90         INDEX_FTP_PROXY_PORT,
91         INDEX_HTTP_PROXY_NAME,
92         INDEX_HTTP_PROXY_PORT
93     };
94 
95     Impl();
96 
97     star::uno::Any getProperty(Index nIndex);
98 
99     void
100     setProperty(Index nIndex, star::uno::Any const & rValue, bool bFlush);
101 
flush()102     inline void flush() { Commit(); }
103 
104     void
105     addPropertiesChangeListener(
106         star::uno::Sequence< rtl::OUString > const & rPropertyNames,
107         star::uno::Reference< star::beans::XPropertiesChangeListener > const &
108             rListener);
109 
110     void
111     removePropertiesChangeListener(
112         star::uno::Sequence< rtl::OUString > const & rPropertyNames,
113         star::uno::Reference< star::beans::XPropertiesChangeListener > const &
114             rListener);
115 
116 private:
117     enum { ENTRY_COUNT = INDEX_HTTP_PROXY_PORT + 1 };
118 
119     struct Entry
120     {
121         enum State { UNKNOWN, KNOWN, MODIFIED };
122 
EntrySvtInetOptions::Impl::Entry123         inline Entry(): m_eState(UNKNOWN) {}
124 
125         rtl::OUString m_aName;
126         star::uno::Any m_aValue;
127         State m_eState;
128     };
129 
130     // MSVC has problems with the below Map type when
131     // star::uno::Reference< star::beans::XPropertiesChangeListener > is not
132     // wrapped in class Listener:
133     class Listener:
134         public star::uno::Reference< star::beans::XPropertiesChangeListener >
135     {
136     public:
Listener(star::uno::Reference<star::beans::XPropertiesChangeListener> const & rListener)137         Listener(star::uno::Reference<
138                          star::beans::XPropertiesChangeListener > const &
139                      rListener):
140             star::uno::Reference< star::beans::XPropertiesChangeListener >(
141                 rListener)
142         {}
143     };
144 
145     typedef std::map< Listener, std::set< rtl::OUString > > Map;
146 
147     osl::Mutex m_aMutex;
148     Entry m_aEntries[ENTRY_COUNT];
149     Map m_aListeners;
150 
~Impl()151     virtual inline ~Impl() { Commit(); }
152 
153     virtual void Notify(star::uno::Sequence< rtl::OUString > const & rKeys);
154 
155     virtual void Commit();
156 
157     void notifyListeners(star::uno::Sequence< rtl::OUString > const & rKeys);
158 };
159 
160 //============================================================================
161 // virtual
162 void
Notify(star::uno::Sequence<rtl::OUString> const & rKeys)163 SvtInetOptions::Impl::Notify(star::uno::Sequence< rtl::OUString > const &
164                                  rKeys)
165 {
166     {
167         osl::MutexGuard aGuard(m_aMutex);
168         for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
169             for (sal_Int32 j = 0; j < ENTRY_COUNT; ++j)
170                 if (rKeys[i] == m_aEntries[j].m_aName)
171                 {
172                     m_aEntries[j].m_eState = Entry::UNKNOWN;
173                     break;
174                 }
175     }
176     notifyListeners(rKeys);
177 }
178 
179 //============================================================================
180 // virtual
Commit()181 void SvtInetOptions::Impl::Commit()
182 {
183     star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
184     star::uno::Sequence< star::uno::Any > aValues(ENTRY_COUNT);
185     sal_Int32 nCount = 0;
186     {
187         osl::MutexGuard aGuard(m_aMutex);
188         for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
189             if (m_aEntries[i].m_eState == Entry::MODIFIED)
190             {
191                 aKeys[nCount] = m_aEntries[i].m_aName;
192                 aValues[nCount] = m_aEntries[i].m_aValue;
193                 ++nCount;
194                 m_aEntries[i].m_eState = Entry::KNOWN;
195             }
196     }
197     if (nCount > 0)
198     {
199         aKeys.realloc(nCount);
200         aValues.realloc(nCount);
201         PutProperties(aKeys, aValues);
202     }
203 }
204 
205 //============================================================================
206 void
notifyListeners(star::uno::Sequence<rtl::OUString> const & rKeys)207 SvtInetOptions::Impl::notifyListeners(
208     star::uno::Sequence< rtl::OUString > const & rKeys)
209 {
210         typedef std::pair< star::uno::Reference< star::beans::XPropertiesChangeListener >,
211                            star::uno::Sequence< star::beans::PropertyChangeEvent > > Listen2EventPair;
212         typedef std::vector< Listen2EventPair > NotificationList;
213     NotificationList aNotifications;
214     {
215         osl::MutexGuard aGuard(m_aMutex);
216         aNotifications.reserve(m_aListeners.size());
217         Map::const_iterator aMapEnd(m_aListeners.end());
218         for (Map::const_iterator aIt(m_aListeners.begin()); aIt != aMapEnd;
219              ++aIt)
220         {
221             const Map::mapped_type &rSet = aIt->second;
222             Map::mapped_type::const_iterator aSetEnd(rSet.end());
223             star::uno::Sequence< star::beans::PropertyChangeEvent >
224                 aEvents(rKeys.getLength());
225             sal_Int32 nCount = 0;
226             for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
227             {
228                 rtl::OUString
229                     aTheKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
230                                               "Inet/")));
231                 aTheKey += rKeys[i];
232                 if (rSet.find(aTheKey) != aSetEnd)
233                 {
234                     aEvents[nCount].PropertyName = aTheKey;
235                     aEvents[nCount].PropertyHandle = -1;
236                     ++nCount;
237                 }
238             }
239             if (nCount > 0)
240                 aNotifications.push_back( Listen2EventPair( aIt->first, aEvents));
241         }
242     }
243     for (NotificationList::size_type i = 0; i < aNotifications.size(); ++i)
244         if (aNotifications[i].first.is())
245             aNotifications[i].first->
246                 propertiesChange(aNotifications[i].second);
247 }
248 
249 //============================================================================
Impl()250 SvtInetOptions::Impl::Impl():
251     ConfigItem(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Inet/Settings")))
252 {
253     m_aEntries[INDEX_NO_PROXY].m_aName
254         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetNoProxy"));
255     m_aEntries[INDEX_PROXY_TYPE].m_aName
256         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetProxyType"));
257     m_aEntries[INDEX_FTP_PROXY_NAME].m_aName
258         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyName"));
259     m_aEntries[INDEX_FTP_PROXY_PORT].m_aName
260         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyPort"));
261     m_aEntries[INDEX_HTTP_PROXY_NAME].m_aName
262         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyName"));
263     m_aEntries[INDEX_HTTP_PROXY_PORT].m_aName
264         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyPort"));
265 
266     star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
267     for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
268         aKeys[i] = m_aEntries[i].m_aName;
269     if (!EnableNotification(aKeys))
270         OSL_ENSURE(false,
271                    "SvtInetOptions::Impl::Impl(): Bad EnableNotifications()");
272 }
273 
274 //============================================================================
getProperty(Index nPropIndex)275 star::uno::Any SvtInetOptions::Impl::getProperty(Index nPropIndex)
276 {
277     for (int nTryCount = 0; nTryCount < 10; ++nTryCount)
278     {
279         {
280             osl::MutexGuard aGuard(m_aMutex);
281             if (m_aEntries[nPropIndex].m_eState != Entry::UNKNOWN)
282                 return m_aEntries[nPropIndex].m_aValue;
283         }
284         star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
285         int nIndices[ENTRY_COUNT];
286         sal_Int32 nCount = 0;
287         {
288             osl::MutexGuard aGuard(m_aMutex);
289             for (int i = 0; i < ENTRY_COUNT; ++i)
290                 if (m_aEntries[i].m_eState == Entry::UNKNOWN)
291                 {
292                     aKeys[nCount] = m_aEntries[i].m_aName;
293                     nIndices[nCount] = i;
294                     ++nCount;
295                 }
296         }
297         if (nCount > 0)
298         {
299             aKeys.realloc(nCount);
300             star::uno::Sequence< star::uno::Any >
301                 aValues(GetProperties(aKeys));
302             OSL_ENSURE(aValues.getLength() == nCount,
303                        "SvtInetOptions::Impl::getProperty():"
304                            " Bad GetProperties() result");
305             nCount = std::min(nCount, aValues.getLength());
306             {
307                 osl::MutexGuard aGuard(m_aMutex);
308                 for (sal_Int32 i = 0; i < nCount; ++i)
309                 {
310                     int nIndex = nIndices[i];
311                     if (m_aEntries[nIndex].m_eState == Entry::UNKNOWN)
312                     {
313                         m_aEntries[nIndices[i]].m_aValue = aValues[i];
314                         m_aEntries[nIndices[i]].m_eState = Entry::KNOWN;
315                     }
316                 }
317             }
318         }
319     }
320     OSL_ENSURE(false,
321                "SvtInetOptions::Impl::getProperty(): Possible life lock");
322     {
323         osl::MutexGuard aGuard(m_aMutex);
324         return m_aEntries[nPropIndex].m_aValue;
325     }
326 }
327 
328 //============================================================================
setProperty(Index nIndex,star::uno::Any const & rValue,bool bFlush)329 void SvtInetOptions::Impl::setProperty(Index nIndex,
330                                        star::uno::Any const & rValue,
331                                        bool bFlush)
332 {
333     SetModified();
334     {
335         osl::MutexGuard aGuard(m_aMutex);
336         m_aEntries[nIndex].m_aValue = rValue;
337         m_aEntries[nIndex].m_eState = bFlush ? Entry::KNOWN : Entry::MODIFIED;
338     }
339 
340     star::uno::Sequence< rtl::OUString > aKeys(1);
341     aKeys[0] = m_aEntries[nIndex].m_aName;
342     if (bFlush)
343     {
344         star::uno::Sequence< star::uno::Any > aValues(1);
345         aValues[0] = rValue;
346         PutProperties(aKeys, aValues);
347     }
348     else
349         notifyListeners(aKeys);
350 }
351 
352 //============================================================================
353 void
addPropertiesChangeListener(star::uno::Sequence<rtl::OUString> const & rPropertyNames,star::uno::Reference<star::beans::XPropertiesChangeListener> const & rListener)354 SvtInetOptions::Impl::addPropertiesChangeListener(
355     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
356     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
357         rListener)
358 {
359     osl::MutexGuard aGuard(m_aMutex);
360     Map::mapped_type & rEntry = m_aListeners[rListener];
361     for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
362         rEntry.insert(rPropertyNames[i]);
363 }
364 
365 //============================================================================
366 void
removePropertiesChangeListener(star::uno::Sequence<rtl::OUString> const & rPropertyNames,star::uno::Reference<star::beans::XPropertiesChangeListener> const & rListener)367 SvtInetOptions::Impl::removePropertiesChangeListener(
368     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
369     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
370         rListener)
371 {
372     osl::MutexGuard aGuard(m_aMutex);
373     Map::iterator aIt(m_aListeners.find(rListener));
374     if (aIt != m_aListeners.end())
375     {
376         for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
377             aIt->second.erase(rPropertyNames[i]);
378         if (aIt->second.empty())
379             m_aListeners.erase(aIt);
380     }
381 }
382 
383 //============================================================================
384 //
385 //  SvtInetOptions
386 //
387 //============================================================================
388 
389 namespace
390 {
391     class LocalSingleton : public rtl::Static< osl::Mutex, LocalSingleton >
392     {
393     };
394 }
395 
396 // static
397 SvtInetOptions::Impl * SvtInetOptions::m_pImpl = 0;
398 
399 //============================================================================
SvtInetOptions()400 SvtInetOptions::SvtInetOptions()
401 {
402     osl::MutexGuard aGuard(LocalSingleton::get());
403     if (!m_pImpl)
404     {
405         RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtInetOptions_Impl::ctor()");
406         m_pImpl = new Impl;
407 
408         ItemHolder1::holdConfigItem(E_INETOPTIONS);
409     }
410     m_pImpl->acquire();
411 }
412 
413 //============================================================================
~SvtInetOptions()414 SvtInetOptions::~SvtInetOptions()
415 {
416     osl::MutexGuard aGuard(LocalSingleton::get());
417     if (m_pImpl->release() == 0)
418         m_pImpl = 0;
419 }
420 
421 //============================================================================
GetProxyNoProxy() const422 rtl::OUString SvtInetOptions::GetProxyNoProxy() const
423 {
424     return takeAny< rtl::OUString >(m_pImpl->
425                                         getProperty(Impl::INDEX_NO_PROXY));
426 }
427 
428 //============================================================================
GetProxyType() const429 sal_Int32 SvtInetOptions::GetProxyType() const
430 {
431     return takeAny< sal_Int32 >(m_pImpl->
432                                     getProperty(Impl::INDEX_PROXY_TYPE));
433 }
434 
435 //============================================================================
GetProxyFtpName() const436 rtl::OUString SvtInetOptions::GetProxyFtpName() const
437 {
438     return takeAny< rtl::OUString >(m_pImpl->
439                                         getProperty(
440                                             Impl::INDEX_FTP_PROXY_NAME));
441 }
442 
443 //============================================================================
GetProxyFtpPort() const444 sal_Int32 SvtInetOptions::GetProxyFtpPort() const
445 {
446     return takeAny< sal_Int32 >(m_pImpl->
447                                     getProperty(Impl::INDEX_FTP_PROXY_PORT));
448 }
449 
450 //============================================================================
GetProxyHttpName() const451 rtl::OUString SvtInetOptions::GetProxyHttpName() const
452 {
453     return takeAny< rtl::OUString >(m_pImpl->
454                                         getProperty(
455                                             Impl::INDEX_HTTP_PROXY_NAME));
456 }
457 
458 //============================================================================
GetProxyHttpPort() const459 sal_Int32 SvtInetOptions::GetProxyHttpPort() const
460 {
461     return takeAny< sal_Int32 >(m_pImpl->
462                                     getProperty(Impl::INDEX_HTTP_PROXY_PORT));
463 }
464 
465 //============================================================================
SetProxyNoProxy(rtl::OUString const & rValue,bool bFlush)466 void SvtInetOptions::SetProxyNoProxy(rtl::OUString const & rValue,
467                                      bool bFlush)
468 {
469     m_pImpl->setProperty(Impl::INDEX_NO_PROXY,
470                          star::uno::makeAny(rValue),
471                          bFlush);
472 }
473 
474 //============================================================================
SetProxyType(ProxyType eValue,bool bFlush)475 void SvtInetOptions::SetProxyType(ProxyType eValue, bool bFlush)
476 {
477     m_pImpl->setProperty(Impl::INDEX_PROXY_TYPE,
478                          star::uno::makeAny(sal_Int32(eValue)),
479                          bFlush);
480 }
481 
482 //============================================================================
SetProxyFtpName(rtl::OUString const & rValue,bool bFlush)483 void SvtInetOptions::SetProxyFtpName(rtl::OUString const & rValue,
484                                      bool bFlush)
485 {
486     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_NAME,
487                          star::uno::makeAny(rValue),
488                          bFlush);
489 }
490 
491 //============================================================================
SetProxyFtpPort(sal_Int32 nValue,bool bFlush)492 void SvtInetOptions::SetProxyFtpPort(sal_Int32 nValue, bool bFlush)
493 {
494     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_PORT,
495                          star::uno::makeAny(nValue),
496                          bFlush);
497 }
498 
499 //============================================================================
SetProxyHttpName(rtl::OUString const & rValue,bool bFlush)500 void SvtInetOptions::SetProxyHttpName(rtl::OUString const & rValue,
501                                       bool bFlush)
502 {
503     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_NAME,
504                          star::uno::makeAny(rValue),
505                          bFlush);
506 }
507 
508 //============================================================================
SetProxyHttpPort(sal_Int32 nValue,bool bFlush)509 void SvtInetOptions::SetProxyHttpPort(sal_Int32 nValue, bool bFlush)
510 {
511     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_PORT,
512                          star::uno::makeAny(nValue),
513                          bFlush);
514 }
515 
516 //============================================================================
flush()517 void SvtInetOptions::flush()
518 {
519     m_pImpl->flush();
520 }
521 
522 //============================================================================
523 void
addPropertiesChangeListener(star::uno::Sequence<rtl::OUString> const & rPropertyNames,star::uno::Reference<star::beans::XPropertiesChangeListener> const & rListener)524 SvtInetOptions::addPropertiesChangeListener(
525     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
526     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
527         rListener)
528 {
529     m_pImpl->addPropertiesChangeListener(rPropertyNames, rListener);
530 }
531 
532 //============================================================================
533 void
removePropertiesChangeListener(star::uno::Sequence<rtl::OUString> const & rPropertyNames,star::uno::Reference<star::beans::XPropertiesChangeListener> const & rListener)534 SvtInetOptions::removePropertiesChangeListener(
535     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
536     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
537         rListener)
538 {
539     m_pImpl->removePropertiesChangeListener(rPropertyNames, rListener);
540 }
541