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