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