Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : /*TODO
30 : : - change "singleton" behaviour by using new helper ::comhelper::SingletonRef
31 : : - rename method exist() to existHandlerForURL() or similar one
32 : : - may its a good idea to replace struct ProtocolHandler by css::beans::NamedValue type?!
33 : : */
34 : :
35 : : #include <classes/protocolhandlercache.hxx>
36 : : #include <classes/converter.hxx>
37 : : #include <threadhelp/readguard.hxx>
38 : : #include <threadhelp/writeguard.hxx>
39 : : #include <threadhelp/lockhelper.hxx>
40 : :
41 : : #include <tools/wldcrd.hxx>
42 : : #include <unotools/configpaths.hxx>
43 : : #include <rtl/ustrbuf.hxx>
44 : :
45 : : namespace framework{
46 : :
47 : : /**
48 : : @short overloaded index operator of hash map to support pattern key search
49 : : @descr All keys inside this hash map are URL pattern which points to an uno
50 : : implementation name of a protocol handler service which is registered
51 : : for this pattern. This operator makes it easy to find such registered
52 : : handler by using a full qualified URL and compare it with all pattern
53 : : keys.
54 : :
55 : : @param sURL
56 : : the full qualified URL which should match to a registered pattern
57 : :
58 : : @return An iterator which points to the found item inside the hash or PatternHash::end()
59 : : if no pattern match this given <var>sURL</var>.
60 : : */
61 : 3782 : PatternHash::iterator PatternHash::findPatternKey( const ::rtl::OUString& sURL )
62 : : {
63 : 3782 : PatternHash::iterator pItem = this->begin();
64 [ + + ]: 34048 : while( pItem!=this->end() )
65 : : {
66 [ + - ][ + - ]: 34046 : WildCard aPattern(pItem->first);
67 [ + - ][ + - ]: 34046 : if (aPattern.Matches(sURL))
[ + - ][ + + ]
68 : : break;
69 [ + + ]: 64312 : ++pItem;
70 [ + - ]: 34046 : }
71 : 3782 : return pItem;
72 : : }
73 : :
74 : : //_________________________________________________________________________________________________________________
75 : :
76 : : /**
77 : : @short initialize static member of class HandlerCache
78 : : @descr We use a singleton pattern to implement this handler cache.
79 : : That means it use two static member list to hold all neccessary informations
80 : : and a ref count mechanism to create/destroy it on demand.
81 : : */
82 : : HandlerHash* HandlerCache::m_pHandler = NULL;
83 : : PatternHash* HandlerCache::m_pPattern = NULL;
84 : : sal_Int32 HandlerCache::m_nRefCount = 0 ;
85 : : HandlerCFGAccess* HandlerCache::m_pConfig = NULL;
86 : :
87 : : //_________________________________________________________________________________________________________________
88 : :
89 : : /**
90 : : @short ctor of the cache of all registered protoco handler
91 : : @descr It tries to open the right configuration package automaticly
92 : : and fill the internal structures. After that the cache can be
93 : : used for read access on this data and perform some search
94 : : operations on it.
95 : : */
96 : 2317 : HandlerCache::HandlerCache()
97 : : {
98 : : /* SAFE */{
99 [ + - ][ + - ]: 2317 : WriteGuard aGlobalLock( LockHelper::getGlobalLock() );
100 : :
101 [ + + ]: 2317 : if (m_nRefCount==0)
102 : : {
103 [ + - ][ + - ]: 267 : m_pHandler = new HandlerHash();
104 [ + - ][ + - ]: 267 : m_pPattern = new PatternHash();
105 [ + - ][ + - ]: 267 : m_pConfig = new HandlerCFGAccess(PACKAGENAME_PROTOCOLHANDLER);
[ + - ]
106 [ + - ]: 267 : m_pConfig->read(&m_pHandler,&m_pPattern);
107 : 267 : m_pConfig->setCache(this);
108 : : }
109 : :
110 [ + - ]: 2317 : ++m_nRefCount;
111 : : /* SAFE */}
112 : 2317 : }
113 : :
114 : : //_________________________________________________________________________________________________________________
115 : :
116 : : /**
117 : : @short dtor of the cache
118 : : @descr It frees all used memory. In further implementations (may if we support write access too)
119 : : it's a good place to flush changes back to the configuration - but not needed yet.
120 : : */
121 : 2168 : HandlerCache::~HandlerCache()
122 : : {
123 : : /* SAFE */{
124 [ + - ][ + - ]: 2168 : WriteGuard aGlobalLock( LockHelper::getGlobalLock() );
125 : :
126 [ + + ]: 2168 : if( m_nRefCount==1)
127 : : {
128 : 253 : m_pConfig->setCache(NULL);
129 [ + - ]: 253 : m_pHandler->free();
130 [ + - ]: 253 : m_pPattern->free();
131 : :
132 [ + - ][ + - ]: 253 : delete m_pConfig;
133 [ + - ][ + - ]: 253 : delete m_pHandler;
134 [ + - ][ + - ]: 253 : delete m_pPattern;
135 : 253 : m_pConfig = NULL;
136 : 253 : m_pHandler= NULL;
137 : 253 : m_pPattern= NULL;
138 : : }
139 : :
140 [ + - ]: 2168 : --m_nRefCount;
141 : : /* SAFE */}
142 [ - + ]: 2168 : }
143 : :
144 : : //_________________________________________________________________________________________________________________
145 : :
146 : : /**
147 : : @short dtor of the cache
148 : : @descr It frees all used memory. In further implementations (may if we support write access too)
149 : : it's a good place to flush changes back to the configuration - but not needed yet.
150 : : */
151 : 3782 : sal_Bool HandlerCache::search( const ::rtl::OUString& sURL, ProtocolHandler* pReturn ) const
152 : : {
153 : 3782 : sal_Bool bFound = sal_False;
154 : : /* SAFE */{
155 [ + - ][ + - ]: 3782 : ReadGuard aReadLock( LockHelper::getGlobalLock() );
156 [ + - ]: 3782 : PatternHash::const_iterator pItem = m_pPattern->findPatternKey(sURL);
157 [ + + ][ + - ]: 3782 : if (pItem!=m_pPattern->end())
158 : : {
159 [ + - ][ + - ]: 3780 : *pReturn = (*m_pHandler)[pItem->second];
[ + - ]
160 : 3780 : bFound = sal_True;
161 [ + - ]: 3782 : }
162 : : /* SAFE */}
163 : 3782 : return bFound;
164 : : }
165 : :
166 : : //_________________________________________________________________________________________________________________
167 : :
168 : : /**
169 : : @short search for a registered handler by using an URL struct
170 : : @descr We combine neccessary parts of this struct to a valid URL string
171 : : and call our other search method ...
172 : : It's a helper for outside code.
173 : : */
174 : 3782 : sal_Bool HandlerCache::search( const css::util::URL& aURL, ProtocolHandler* pReturn ) const
175 : : {
176 : 3782 : return search( aURL.Complete, pReturn );
177 : : }
178 : :
179 : : //_________________________________________________________________________________________________________________
180 : 0 : void HandlerCache::takeOver(HandlerHash* pHandler, PatternHash* pPattern)
181 : : {
182 : : // SAFE ->
183 [ # # ][ # # ]: 0 : WriteGuard aWriteLock( LockHelper::getGlobalLock() );
184 : :
185 : 0 : HandlerHash* pOldHandler = m_pHandler;
186 : 0 : PatternHash* pOldPattern = m_pPattern;
187 : :
188 : 0 : m_pHandler = pHandler;
189 : 0 : m_pPattern = pPattern;
190 : :
191 [ # # ]: 0 : pOldHandler->free();
192 [ # # ]: 0 : pOldPattern->free();
193 [ # # ][ # # ]: 0 : delete pOldHandler;
194 [ # # ][ # # ]: 0 : delete pOldPattern;
195 : :
196 [ # # ][ # # ]: 0 : aWriteLock.unlock();
197 : : // <- SAFE
198 : 0 : }
199 : :
200 : : //_________________________________________________________________________________________________________________
201 : :
202 : : /**
203 : : @short dtor of the config access class
204 : : @descr It opens the configuration package automaticly by using base class mechanism.
205 : : After that "read()" method of this class should be called to use it.
206 : :
207 : : @param sPackage
208 : : specifies the package name of the configuration data which should be used
209 : : */
210 : 267 : HandlerCFGAccess::HandlerCFGAccess( const ::rtl::OUString& sPackage )
211 : 267 : : ConfigItem( sPackage )
212 : : {
213 [ + - ]: 267 : css::uno::Sequence< ::rtl::OUString > lListenPaths(1);
214 [ + - ][ + - ]: 267 : lListenPaths[0] = SETNAME_HANDLER;
215 [ + - ][ + - ]: 267 : EnableNotification(lListenPaths);
216 : 267 : }
217 : :
218 : : //_________________________________________________________________________________________________________________
219 : :
220 : : /**
221 : : @short use base class mechanism to fill given structures
222 : : @descr User use us as a wrapper between configuration api and his internal structures.
223 : : He give us some pointer to his member and we fill it.
224 : :
225 : : @param pHandler
226 : : pointer to a list of protocol handler infos
227 : :
228 : : @param pPattern
229 : : reverse map of handler pattern to her uno names
230 : : */
231 : 267 : void HandlerCFGAccess::read( HandlerHash** ppHandler ,
232 : : PatternHash** ppPattern )
233 : : {
234 : : // list of all uno implementation names without encoding
235 [ + - ][ + - ]: 267 : css::uno::Sequence< ::rtl::OUString > lNames = GetNodeNames( SETNAME_HANDLER, ::utl::CONFIG_NAME_LOCAL_PATH );
236 : 267 : sal_Int32 nSourceCount = lNames.getLength();
237 : 267 : sal_Int32 nTargetCount = nSourceCount;
238 : : // list of all full qualified path names of configuration entries
239 [ + - ]: 267 : css::uno::Sequence< ::rtl::OUString > lFullNames ( nTargetCount );
240 : :
241 : : // expand names to full path names
242 : 267 : sal_Int32 nSource=0;
243 : 267 : sal_Int32 nTarget=0;
244 [ + + ]: 2595 : for( nSource=0; nSource<nSourceCount; ++nSource )
245 : : {
246 [ + - ][ + - ]: 2328 : ::rtl::OUStringBuffer sPath( SETNAME_HANDLER );
247 [ + - ][ + - ]: 2328 : sPath.append(CFG_PATH_SEPERATOR);
248 [ + - ][ + - ]: 2328 : sPath.append(lNames[nSource]);
249 [ + - ][ + - ]: 2328 : sPath.append(CFG_PATH_SEPERATOR);
250 [ + - ][ + - ]: 2328 : sPath.append(PROPERTY_PROTOCOLS);
251 : :
252 [ + - ][ + - ]: 2328 : lFullNames[nTarget] = sPath.makeStringAndClear();
253 : 2328 : ++nTarget;
254 : 2328 : }
255 : :
256 : : // get values at all
257 [ + - ]: 267 : css::uno::Sequence< css::uno::Any > lValues = GetProperties( lFullNames );
258 : : LOG_ASSERT2( lFullNames.getLength()!=lValues.getLength(), "HandlerCFGAccess::read()", "Miss some configuration values of handler set!" )
259 : :
260 : : // fill structures
261 : 267 : nSource = 0;
262 [ + + ]: 2595 : for( nTarget=0; nTarget<nTargetCount; ++nTarget )
263 : : {
264 : : // create it new for every loop to guarantee a real empty object!
265 [ + - ]: 2328 : ProtocolHandler aHandler;
266 [ + - ][ + - ]: 2328 : aHandler.m_sUNOName = ::utl::extractFirstFromConfigurationPath(lNames[nSource]);
267 : :
268 : : // unpack all values of this handler
269 [ + - ]: 2328 : css::uno::Sequence< ::rtl::OUString > lTemp;
270 [ + - ][ + - ]: 2328 : lValues[nTarget] >>= lTemp;
271 [ + - ][ + - ]: 2328 : aHandler.m_lProtocols = Converter::convert_seqOUString2OUStringList(lTemp);
[ + - ]
272 : :
273 : : // register his pattern into the performance search hash
274 [ + - ][ + + ]: 9846 : for (OUStringList::iterator pItem =aHandler.m_lProtocols.begin();
275 : 4923 : pItem!=aHandler.m_lProtocols.end() ;
276 : : ++pItem )
277 : : {
278 [ + - ][ + - ]: 2595 : (**ppPattern)[*pItem] = lNames[nSource];
279 : : }
280 : :
281 : : // ï¿œnsert the handler info into the normal handler cache
282 [ + - ][ + - ]: 2328 : (**ppHandler)[lNames[nSource]] = aHandler;
[ + - ]
283 : 2328 : ++nSource;
284 [ + - ][ + - ]: 2595 : }
[ + - ][ + - ]
[ + - ]
285 : 267 : }
286 : :
287 : : //_________________________________________________________________________________________________________________
288 : 0 : void HandlerCFGAccess::Notify(const css::uno::Sequence< rtl::OUString >& /*lPropertyNames*/)
289 : : {
290 [ # # ][ # # ]: 0 : HandlerHash* pHandler = new HandlerHash;
291 [ # # ][ # # ]: 0 : PatternHash* pPattern = new PatternHash;
292 : :
293 [ # # ]: 0 : read(&pHandler, &pPattern);
294 [ # # ]: 0 : if (m_pCache)
295 [ # # ]: 0 : m_pCache->takeOver(pHandler, pPattern);
296 : : else
297 : : {
298 [ # # ][ # # ]: 0 : delete pHandler;
299 [ # # ][ # # ]: 0 : delete pPattern;
300 : : }
301 : 0 : }
302 : :
303 : 0 : void HandlerCFGAccess::Commit()
304 : : {
305 : 0 : }
306 : :
307 : : } // namespace framework
308 : :
309 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|