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 /*TODO 32 - change "singleton" behaviour by using new helper ::comhelper::SingletonRef 33 - rename method exist() to existHandlerForURL() or similar one 34 - may its a good idea to replace struct ProtocolHandler by css::beans::NamedValue type?! 35 */ 36 37 //_________________________________________________________________________________________________________________ 38 // my own includes 39 //_________________________________________________________________________________________________________________ 40 41 #include <classes/protocolhandlercache.hxx> 42 #include <classes/converter.hxx> 43 #include <threadhelp/readguard.hxx> 44 #include <threadhelp/writeguard.hxx> 45 #include <threadhelp/lockhelper.hxx> 46 47 //_________________________________________________________________________________________________________________ 48 // interface includes 49 //_________________________________________________________________________________________________________________ 50 51 //_________________________________________________________________________________________________________________ 52 // other includes 53 //_________________________________________________________________________________________________________________ 54 #include <tools/wldcrd.hxx> 55 #include <unotools/configpathes.hxx> 56 #include <rtl/ustrbuf.hxx> 57 58 //_________________________________________________________________________________________________________________ 59 // namespace 60 //_________________________________________________________________________________________________________________ 61 62 namespace framework{ 63 64 //_________________________________________________________________________________________________________________ 65 // non exported const 66 //_________________________________________________________________________________________________________________ 67 68 //_________________________________________________________________________________________________________________ 69 // non exported definitions 70 //_________________________________________________________________________________________________________________ 71 72 /** 73 @short overloaded index operator of hash map to support pattern key search 74 @descr All keys inside this hash map are URL pattern which points to an uno 75 implementation name of a protocol handler service which is registered 76 for this pattern. This operator makes it easy to find such registered 77 handler by using a full qualified URL and compare it with all pattern 78 keys. 79 80 @param sURL 81 the full qualified URL which should match to a registered pattern 82 83 @return An iterator which points to the found item inside the hash or PatternHash::end() 84 if no pattern match this given <var>sURL</var>. 85 86 @modified 30.04.2002 09:52, as96863 87 */ 88 PatternHash::iterator PatternHash::findPatternKey( const ::rtl::OUString& sURL ) 89 { 90 PatternHash::iterator pItem = this->begin(); 91 while( pItem!=this->end() ) 92 { 93 WildCard aPattern(pItem->first); 94 if (aPattern.Matches(sURL)) 95 break; 96 ++pItem; 97 } 98 return pItem; 99 } 100 101 //_________________________________________________________________________________________________________________ 102 103 /** 104 @short initialize static member of class HandlerCache 105 @descr We use a singleton pattern to implement this handler cache. 106 That means it use two static member list to hold all neccessary informations 107 and a ref count mechanism to create/destroy it on demand. 108 109 @modified 30.04.2002 11:13, as96863 110 */ 111 HandlerHash* HandlerCache::m_pHandler = NULL; 112 PatternHash* HandlerCache::m_pPattern = NULL; 113 sal_Int32 HandlerCache::m_nRefCount = 0 ; 114 HandlerCFGAccess* HandlerCache::m_pConfig = NULL; 115 116 //_________________________________________________________________________________________________________________ 117 118 /** 119 @short ctor of the cache of all registered protoco handler 120 @descr It tries to open the right configuration package automaticly 121 and fill the internal structures. After that the cache can be 122 used for read access on this data and perform some search 123 operations on it. 124 125 @modified 30.04.2002 10:02, as96863 126 */ 127 HandlerCache::HandlerCache() 128 { 129 /* SAFE */{ 130 WriteGuard aGlobalLock( LockHelper::getGlobalLock() ); 131 132 if (m_nRefCount==0) 133 { 134 m_pHandler = new HandlerHash(); 135 m_pPattern = new PatternHash(); 136 m_pConfig = new HandlerCFGAccess(PACKAGENAME_PROTOCOLHANDLER); 137 m_pConfig->read(&m_pHandler,&m_pPattern); 138 m_pConfig->setCache(this); 139 } 140 141 ++m_nRefCount; 142 /* SAFE */} 143 } 144 145 //_________________________________________________________________________________________________________________ 146 147 /** 148 @short dtor of the cache 149 @descr It frees all used memory. In further implementations (may if we support write access too) 150 it's a good place to flush changes back to the configuration - but not needed yet. 151 152 @modified 30.04.2002 09:54, as96863 153 */ 154 HandlerCache::~HandlerCache() 155 { 156 /* SAFE */{ 157 WriteGuard aGlobalLock( LockHelper::getGlobalLock() ); 158 159 if( m_nRefCount==1) 160 { 161 m_pConfig->setCache(NULL); 162 m_pHandler->free(); 163 m_pPattern->free(); 164 165 delete m_pConfig; 166 delete m_pHandler; 167 delete m_pPattern; 168 m_pConfig = NULL; 169 m_pHandler= NULL; 170 m_pPattern= NULL; 171 } 172 173 --m_nRefCount; 174 /* SAFE */} 175 } 176 177 //_________________________________________________________________________________________________________________ 178 179 /** 180 @short dtor of the cache 181 @descr It frees all used memory. In further implementations (may if we support write access too) 182 it's a good place to flush changes back to the configuration - but not needed yet. 183 184 @modified 30.04.2002 09:54, as96863 185 */ 186 sal_Bool HandlerCache::search( const ::rtl::OUString& sURL, ProtocolHandler* pReturn ) const 187 { 188 sal_Bool bFound = sal_False; 189 /* SAFE */{ 190 ReadGuard aReadLock( LockHelper::getGlobalLock() ); 191 PatternHash::const_iterator pItem = m_pPattern->findPatternKey(sURL); 192 if (pItem!=m_pPattern->end()) 193 { 194 *pReturn = (*m_pHandler)[pItem->second]; 195 bFound = sal_True; 196 } 197 /* SAFE */} 198 return bFound; 199 } 200 201 //_________________________________________________________________________________________________________________ 202 203 /** 204 @short search for a registered handler by using an URL struct 205 @descr We combine neccessary parts of this struct to a valid URL string 206 and call our other search method ... 207 It's a helper for outside code. 208 209 @modified 30.04.2002 09:54, as96863 210 */ 211 sal_Bool HandlerCache::search( const css::util::URL& aURL, ProtocolHandler* pReturn ) const 212 { 213 return search( aURL.Complete, pReturn ); 214 } 215 216 //_________________________________________________________________________________________________________________ 217 218 sal_Bool HandlerCache::exists( const ::rtl::OUString& sURL ) const 219 { 220 sal_Bool bFound = sal_False; 221 /* SAFE */{ 222 ReadGuard aReadLock( LockHelper::getGlobalLock() ); 223 PatternHash::const_iterator pItem = m_pPattern->findPatternKey(sURL); 224 bFound = pItem!=m_pPattern->end(); 225 /* SAFE */} 226 return bFound; 227 } 228 229 //_________________________________________________________________________________________________________________ 230 void HandlerCache::takeOver(HandlerHash* pHandler, PatternHash* pPattern) 231 { 232 // SAFE -> 233 WriteGuard aWriteLock( LockHelper::getGlobalLock() ); 234 235 HandlerHash* pOldHandler = m_pHandler; 236 PatternHash* pOldPattern = m_pPattern; 237 238 m_pHandler = pHandler; 239 m_pPattern = pPattern; 240 241 pOldHandler->free(); 242 pOldPattern->free(); 243 delete pOldHandler; 244 delete pOldPattern; 245 246 aWriteLock.unlock(); 247 // <- SAFE 248 } 249 250 //_________________________________________________________________________________________________________________ 251 252 /** 253 @short dtor of the config access class 254 @descr It opens the configuration package automaticly by using base class mechanism. 255 After that "read()" method of this class should be called to use it. 256 257 @param sPackage 258 specifies the package name of the configuration data which should be used 259 260 @modified 30.04.2002 10:06, as96863 261 */ 262 HandlerCFGAccess::HandlerCFGAccess( const ::rtl::OUString& sPackage ) 263 : ConfigItem( sPackage ) 264 { 265 css::uno::Sequence< ::rtl::OUString > lListenPathes(1); 266 lListenPathes[0] = SETNAME_HANDLER; 267 EnableNotification(lListenPathes); 268 } 269 270 //_________________________________________________________________________________________________________________ 271 272 /** 273 @short use base class mechanism to fill given structures 274 @descr User use us as a wrapper between configuration api and his internal structures. 275 He give us some pointer to his member and we fill it. 276 277 @param pHandler 278 pointer to a list of protocol handler infos 279 280 @param pPattern 281 reverse map of handler pattern to her uno names 282 283 @modified 30.04.2002 09:54, as96863 284 */ 285 void HandlerCFGAccess::read( HandlerHash** ppHandler , 286 PatternHash** ppPattern ) 287 { 288 // list of all uno implementation names without encoding 289 css::uno::Sequence< ::rtl::OUString > lNames = GetNodeNames( SETNAME_HANDLER, ::utl::CONFIG_NAME_LOCAL_PATH ); 290 sal_Int32 nSourceCount = lNames.getLength(); 291 sal_Int32 nTargetCount = nSourceCount; 292 // list of all full qualified path names of configuration entries 293 css::uno::Sequence< ::rtl::OUString > lFullNames ( nTargetCount ); 294 295 // expand names to full path names 296 sal_Int32 nSource=0; 297 sal_Int32 nTarget=0; 298 for( nSource=0; nSource<nSourceCount; ++nSource ) 299 { 300 ::rtl::OUStringBuffer sPath( SETNAME_HANDLER ); 301 sPath.append(CFG_PATH_SEPERATOR); 302 sPath.append(lNames[nSource]); 303 sPath.append(CFG_PATH_SEPERATOR); 304 sPath.append(PROPERTY_PROTOCOLS); 305 306 lFullNames[nTarget] = sPath.makeStringAndClear(); 307 ++nTarget; 308 } 309 310 // get values at all 311 css::uno::Sequence< css::uno::Any > lValues = GetProperties( lFullNames ); 312 LOG_ASSERT2( lFullNames.getLength()!=lValues.getLength(), "HandlerCFGAccess::read()", "Miss some configuration values of handler set!" ) 313 314 // fill structures 315 nSource = 0; 316 for( nTarget=0; nTarget<nTargetCount; ++nTarget ) 317 { 318 // create it new for every loop to guarantee a real empty object! 319 ProtocolHandler aHandler; 320 aHandler.m_sUNOName = ::utl::extractFirstFromConfigurationPath(lNames[nSource]); 321 322 // unpack all values of this handler 323 css::uno::Sequence< ::rtl::OUString > lTemp; 324 lValues[nTarget] >>= lTemp; 325 aHandler.m_lProtocols = Converter::convert_seqOUString2OUStringList(lTemp); 326 327 // register his pattern into the performance search hash 328 for (OUStringList::iterator pItem =aHandler.m_lProtocols.begin(); 329 pItem!=aHandler.m_lProtocols.end() ; 330 ++pItem ) 331 { 332 (**ppPattern)[*pItem] = lNames[nSource]; 333 } 334 335 // ï¿œnsert the handler info into the normal handler cache 336 (**ppHandler)[lNames[nSource]] = aHandler; 337 ++nSource; 338 } 339 } 340 341 //_________________________________________________________________________________________________________________ 342 void HandlerCFGAccess::Notify(const css::uno::Sequence< rtl::OUString >& /*lPropertyNames*/) 343 { 344 HandlerHash* pHandler = new HandlerHash; 345 PatternHash* pPattern = new PatternHash; 346 347 read(&pHandler, &pPattern); 348 if (m_pCache) 349 m_pCache->takeOver(pHandler, pPattern); 350 else 351 { 352 delete pHandler; 353 delete pPattern; 354 } 355 } 356 357 void HandlerCFGAccess::Commit() 358 { 359 } 360 361 } // namespace framework 362