xref: /AOO41X/main/unotools/source/config/inetoptions.cxx (revision 5980243063f6840bf3a2e60b2243db5da5e78fa6)
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 
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 
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 
123         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:
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 
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
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
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
207 SvtInetOptions::Impl::notifyListeners(
208     star::uno::Sequence< rtl::OUString > const & rKeys)
209 {
210     typedef
211         std::vector< std::pair< star::uno::Reference<
212                                     star::beans::XPropertiesChangeListener >,
213                                 star::uno::Sequence<
214                                     star::beans::PropertyChangeEvent > > >
215     List;
216     List aNotifications;
217     {
218         osl::MutexGuard aGuard(m_aMutex);
219         aNotifications.reserve(m_aListeners.size());
220         Map::const_iterator aMapEnd(m_aListeners.end());
221         for (Map::const_iterator aIt(m_aListeners.begin()); aIt != aMapEnd;
222              ++aIt)
223         {
224             const Map::mapped_type &rSet = aIt->second;
225             Map::mapped_type::const_iterator aSetEnd(rSet.end());
226             star::uno::Sequence< star::beans::PropertyChangeEvent >
227                 aEvents(rKeys.getLength());
228             sal_Int32 nCount = 0;
229             for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
230             {
231                 rtl::OUString
232                     aTheKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
233                                               "Inet/")));
234                 aTheKey += rKeys[i];
235                 if (rSet.find(aTheKey) != aSetEnd)
236                 {
237                     aEvents[nCount].PropertyName = aTheKey;
238                     aEvents[nCount].PropertyHandle = -1;
239                     ++nCount;
240                 }
241             }
242             if (nCount > 0)
243             {
244                 aEvents.realloc(nCount);
245                 aNotifications.
246                     push_back(std::make_pair< List::value_type::first_type,
247                                               List::value_type::second_type >(
248                                   aIt->first, aEvents));
249             }
250         }
251     }
252     for (List::size_type i = 0; i < aNotifications.size(); ++i)
253         if (aNotifications[i].first.is())
254             aNotifications[i].first->
255                 propertiesChange(aNotifications[i].second);
256 }
257 
258 //============================================================================
259 SvtInetOptions::Impl::Impl():
260     ConfigItem(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Inet/Settings")))
261 {
262     m_aEntries[INDEX_NO_PROXY].m_aName
263         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetNoProxy"));
264     m_aEntries[INDEX_PROXY_TYPE].m_aName
265         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetProxyType"));
266     m_aEntries[INDEX_FTP_PROXY_NAME].m_aName
267         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyName"));
268     m_aEntries[INDEX_FTP_PROXY_PORT].m_aName
269         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyPort"));
270     m_aEntries[INDEX_HTTP_PROXY_NAME].m_aName
271         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyName"));
272     m_aEntries[INDEX_HTTP_PROXY_PORT].m_aName
273         = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyPort"));
274 
275     star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
276     for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
277         aKeys[i] = m_aEntries[i].m_aName;
278     if (!EnableNotification(aKeys))
279         OSL_ENSURE(false,
280                    "SvtInetOptions::Impl::Impl(): Bad EnableNotifications()");
281 }
282 
283 //============================================================================
284 star::uno::Any SvtInetOptions::Impl::getProperty(Index nPropIndex)
285 {
286     for (int nTryCount = 0; nTryCount < 10; ++nTryCount)
287     {
288         {
289             osl::MutexGuard aGuard(m_aMutex);
290             if (m_aEntries[nPropIndex].m_eState != Entry::UNKNOWN)
291                 return m_aEntries[nPropIndex].m_aValue;
292         }
293         star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
294         int nIndices[ENTRY_COUNT];
295         sal_Int32 nCount = 0;
296         {
297             osl::MutexGuard aGuard(m_aMutex);
298             for (int i = 0; i < ENTRY_COUNT; ++i)
299                 if (m_aEntries[i].m_eState == Entry::UNKNOWN)
300                 {
301                     aKeys[nCount] = m_aEntries[i].m_aName;
302                     nIndices[nCount] = i;
303                     ++nCount;
304                 }
305         }
306         if (nCount > 0)
307         {
308             aKeys.realloc(nCount);
309             star::uno::Sequence< star::uno::Any >
310                 aValues(GetProperties(aKeys));
311             OSL_ENSURE(aValues.getLength() == nCount,
312                        "SvtInetOptions::Impl::getProperty():"
313                            " Bad GetProperties() result");
314             nCount = std::min(nCount, aValues.getLength());
315             {
316                 osl::MutexGuard aGuard(m_aMutex);
317                 for (sal_Int32 i = 0; i < nCount; ++i)
318                 {
319                     int nIndex = nIndices[i];
320                     if (m_aEntries[nIndex].m_eState == Entry::UNKNOWN)
321                     {
322                         m_aEntries[nIndices[i]].m_aValue = aValues[i];
323                         m_aEntries[nIndices[i]].m_eState = Entry::KNOWN;
324                     }
325                 }
326             }
327         }
328     }
329     OSL_ENSURE(false,
330                "SvtInetOptions::Impl::getProperty(): Possible life lock");
331     {
332         osl::MutexGuard aGuard(m_aMutex);
333         return m_aEntries[nPropIndex].m_aValue;
334     }
335 }
336 
337 //============================================================================
338 void SvtInetOptions::Impl::setProperty(Index nIndex,
339                                        star::uno::Any const & rValue,
340                                        bool bFlush)
341 {
342     SetModified();
343     {
344         osl::MutexGuard aGuard(m_aMutex);
345         m_aEntries[nIndex].m_aValue = rValue;
346         m_aEntries[nIndex].m_eState = bFlush ? Entry::KNOWN : Entry::MODIFIED;
347     }
348 
349     star::uno::Sequence< rtl::OUString > aKeys(1);
350     aKeys[0] = m_aEntries[nIndex].m_aName;
351     if (bFlush)
352     {
353         star::uno::Sequence< star::uno::Any > aValues(1);
354         aValues[0] = rValue;
355         PutProperties(aKeys, aValues);
356     }
357     else
358         notifyListeners(aKeys);
359 }
360 
361 //============================================================================
362 void
363 SvtInetOptions::Impl::addPropertiesChangeListener(
364     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
365     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
366         rListener)
367 {
368     osl::MutexGuard aGuard(m_aMutex);
369     Map::mapped_type & rEntry = m_aListeners[rListener];
370     for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
371         rEntry.insert(rPropertyNames[i]);
372 }
373 
374 //============================================================================
375 void
376 SvtInetOptions::Impl::removePropertiesChangeListener(
377     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
378     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
379         rListener)
380 {
381     osl::MutexGuard aGuard(m_aMutex);
382     Map::iterator aIt(m_aListeners.find(rListener));
383     if (aIt != m_aListeners.end())
384     {
385         for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
386             aIt->second.erase(rPropertyNames[i]);
387         if (aIt->second.empty())
388             m_aListeners.erase(aIt);
389     }
390 }
391 
392 //============================================================================
393 //
394 //  SvtInetOptions
395 //
396 //============================================================================
397 
398 namespace
399 {
400     class LocalSingleton : public rtl::Static< osl::Mutex, LocalSingleton >
401     {
402     };
403 }
404 
405 // static
406 SvtInetOptions::Impl * SvtInetOptions::m_pImpl = 0;
407 
408 //============================================================================
409 SvtInetOptions::SvtInetOptions()
410 {
411     osl::MutexGuard aGuard(LocalSingleton::get());
412     if (!m_pImpl)
413     {
414         RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtInetOptions_Impl::ctor()");
415         m_pImpl = new Impl;
416 
417         ItemHolder1::holdConfigItem(E_INETOPTIONS);
418     }
419     m_pImpl->acquire();
420 }
421 
422 //============================================================================
423 SvtInetOptions::~SvtInetOptions()
424 {
425     osl::MutexGuard aGuard(LocalSingleton::get());
426     if (m_pImpl->release() == 0)
427         m_pImpl = 0;
428 }
429 
430 //============================================================================
431 rtl::OUString SvtInetOptions::GetProxyNoProxy() const
432 {
433     return takeAny< rtl::OUString >(m_pImpl->
434                                         getProperty(Impl::INDEX_NO_PROXY));
435 }
436 
437 //============================================================================
438 sal_Int32 SvtInetOptions::GetProxyType() const
439 {
440     return takeAny< sal_Int32 >(m_pImpl->
441                                     getProperty(Impl::INDEX_PROXY_TYPE));
442 }
443 
444 //============================================================================
445 rtl::OUString SvtInetOptions::GetProxyFtpName() const
446 {
447     return takeAny< rtl::OUString >(m_pImpl->
448                                         getProperty(
449                                             Impl::INDEX_FTP_PROXY_NAME));
450 }
451 
452 //============================================================================
453 sal_Int32 SvtInetOptions::GetProxyFtpPort() const
454 {
455     return takeAny< sal_Int32 >(m_pImpl->
456                                     getProperty(Impl::INDEX_FTP_PROXY_PORT));
457 }
458 
459 //============================================================================
460 rtl::OUString SvtInetOptions::GetProxyHttpName() const
461 {
462     return takeAny< rtl::OUString >(m_pImpl->
463                                         getProperty(
464                                             Impl::INDEX_HTTP_PROXY_NAME));
465 }
466 
467 //============================================================================
468 sal_Int32 SvtInetOptions::GetProxyHttpPort() const
469 {
470     return takeAny< sal_Int32 >(m_pImpl->
471                                     getProperty(Impl::INDEX_HTTP_PROXY_PORT));
472 }
473 
474 //============================================================================
475 void SvtInetOptions::SetProxyNoProxy(rtl::OUString const & rValue,
476                                      bool bFlush)
477 {
478     m_pImpl->setProperty(Impl::INDEX_NO_PROXY,
479                          star::uno::makeAny(rValue),
480                          bFlush);
481 }
482 
483 //============================================================================
484 void SvtInetOptions::SetProxyType(ProxyType eValue, bool bFlush)
485 {
486     m_pImpl->setProperty(Impl::INDEX_PROXY_TYPE,
487                          star::uno::makeAny(sal_Int32(eValue)),
488                          bFlush);
489 }
490 
491 //============================================================================
492 void SvtInetOptions::SetProxyFtpName(rtl::OUString const & rValue,
493                                      bool bFlush)
494 {
495     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_NAME,
496                          star::uno::makeAny(rValue),
497                          bFlush);
498 }
499 
500 //============================================================================
501 void SvtInetOptions::SetProxyFtpPort(sal_Int32 nValue, bool bFlush)
502 {
503     m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_PORT,
504                          star::uno::makeAny(nValue),
505                          bFlush);
506 }
507 
508 //============================================================================
509 void SvtInetOptions::SetProxyHttpName(rtl::OUString const & rValue,
510                                       bool bFlush)
511 {
512     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_NAME,
513                          star::uno::makeAny(rValue),
514                          bFlush);
515 }
516 
517 //============================================================================
518 void SvtInetOptions::SetProxyHttpPort(sal_Int32 nValue, bool bFlush)
519 {
520     m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_PORT,
521                          star::uno::makeAny(nValue),
522                          bFlush);
523 }
524 
525 //============================================================================
526 void SvtInetOptions::flush()
527 {
528     m_pImpl->flush();
529 }
530 
531 //============================================================================
532 void
533 SvtInetOptions::addPropertiesChangeListener(
534     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
535     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
536         rListener)
537 {
538     m_pImpl->addPropertiesChangeListener(rPropertyNames, rListener);
539 }
540 
541 //============================================================================
542 void
543 SvtInetOptions::removePropertiesChangeListener(
544     star::uno::Sequence< rtl::OUString > const & rPropertyNames,
545     star::uno::Reference< star::beans::XPropertiesChangeListener > const &
546         rListener)
547 {
548     m_pImpl->removePropertiesChangeListener(rPropertyNames, rListener);
549 }
550