1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 - change "singleton" behaviour by using new helper ::comhelper::SingletonRef
22 - rename method exist() to existHandlerForURL() or similar one
23 - may it's a good idea to replace struct ProtocolHandler by css::beans::NamedValue type?!
26 #include <classes/protocolhandlercache.hxx>
27 #include <classes/converter.hxx>
29 #include <tools/wldcrd.hxx>
30 #include <unotools/configpaths.hxx>
31 #include <sal/log.hxx>
32 #include <vcl/svapp.hxx>
34 constexpr OUString SETNAME_HANDLER
= u
"HandlerSet"_ustr
; // name of configuration set inside package
39 @short overloaded index operator of hash map to support pattern key search
40 @descr All keys inside this hash map are URL pattern which points to a uno
41 implementation name of a protocol handler service which is registered
42 for this pattern. This operator makes it easy to find such registered
43 handler by using a full qualified URL and compare it with all pattern
47 the full qualified URL which should match to a registered pattern
49 @return An iterator which points to the found item inside the hash or PatternHash::end()
50 if no pattern match this given <var>sURL</var>.
54 PatternHash::const_iterator
findPatternKey(PatternHash
const * hash
, const OUString
& sURL
)
56 return std::find_if(hash
->begin(), hash
->end(),
57 [&sURL
](const PatternHash::value_type
& rEntry
) {
58 WildCard
aPattern(rEntry
.first
);
59 return aPattern
.Matches(sURL
);
66 @short initialize static member of class HandlerCache
67 @descr We use a singleton pattern to implement this handler cache.
68 That means it use two static member list to hold all necessary information
69 and a ref count mechanism to create/destroy it on demand.
71 std::optional
<HandlerHash
> HandlerCache::s_pHandler
;
72 std::optional
<PatternHash
> HandlerCache::s_pPattern
;
73 sal_Int32
HandlerCache::m_nRefCount
= 0;
74 HandlerCFGAccess
* HandlerCache::s_pConfig
= nullptr;
77 @short ctor of the cache of all registered protocol handler
78 @descr It tries to open the right configuration package automatically
79 and fill the internal structures. After that the cache can be
80 used for read access on this data and perform some search
83 HandlerCache::HandlerCache()
85 SolarMutexGuard aGuard
;
91 s_pConfig
= new HandlerCFGAccess(PACKAGENAME_PROTOCOLHANDLER
);
92 s_pConfig
->read(*s_pHandler
, *s_pPattern
);
93 s_pConfig
->setCache(this);
100 @short dtor of the cache
101 @descr It frees all used memory. In further implementations (may if we support write access too)
102 it's a good place to flush changes back to the configuration - but not needed yet.
104 HandlerCache::~HandlerCache()
106 SolarMutexGuard aGuard
;
110 s_pConfig
->setCache(nullptr);
122 @short dtor of the cache
123 @descr It frees all used memory. In further implementations (may if we support write access too)
124 it's a good place to flush changes back to the configuration - but not needed yet.
126 bool HandlerCache::search( const OUString
& sURL
, ProtocolHandler
* pReturn
) const
130 SolarMutexGuard aGuard
;
132 PatternHash::const_iterator pItem
= findPatternKey(s_pPattern
? &*s_pPattern
: nullptr, sURL
);
133 if (pItem
!= s_pPattern
->end())
135 *pReturn
= (*s_pHandler
)[pItem
->second
];
143 @short search for a registered handler by using a URL struct
144 @descr We combine necessary parts of this struct to a valid URL string
145 and call our other search method ...
146 It's a helper for outside code.
148 bool HandlerCache::search( const css::util::URL
& aURL
, ProtocolHandler
* pReturn
) const
150 return search( aURL
.Complete
, pReturn
);
153 void HandlerCache::takeOver(HandlerHash aHandler
, PatternHash aPattern
)
155 SolarMutexGuard aGuard
;
157 s_pHandler
= std::move(aHandler
);
158 s_pPattern
= std::move(aPattern
);
162 @short dtor of the config access class
163 @descr It opens the configuration package automatically by using base class mechanism.
164 After that "read()" method of this class should be called to use it.
167 specifies the package name of the configuration data which should be used
169 HandlerCFGAccess::HandlerCFGAccess( const OUString
& sPackage
)
170 : ConfigItem(sPackage
)
173 css::uno::Sequence
< OUString
> lListenPaths
{ SETNAME_HANDLER
};
174 EnableNotification(lListenPaths
);
178 @short use base class mechanism to fill given structures
179 @descr User use us as a wrapper between configuration api and his internal structures.
180 He give us some pointer to his member and we fill it.
183 list of protocol handler infos
186 reverse map of handler pattern to her uno names
188 void HandlerCFGAccess::read( HandlerHash
& rHandlerHash
, PatternHash
& rPatternHash
)
190 // list of all uno implementation names without encoding
191 css::uno::Sequence
< OUString
> lNames
= GetNodeNames( SETNAME_HANDLER
, ::utl::ConfigNameFormat::LocalPath
);
192 sal_Int32 nSourceCount
= lNames
.getLength();
193 sal_Int32 nTargetCount
= nSourceCount
;
194 // list of all full qualified path names of configuration entries
195 css::uno::Sequence
< OUString
> lFullNames ( nTargetCount
);
196 auto lFullNamesRange
= asNonConstRange(lFullNames
);
197 // expand names to full path names
200 for( nSource
=0; nSource
<nSourceCount
; ++nSource
)
202 lFullNamesRange
[nTarget
] =
213 css::uno::Sequence
< css::uno::Any
> lValues
= GetProperties( lFullNames
);
214 SAL_WARN_IF( lFullNames
.getLength()!=lValues
.getLength(), "fwk", "HandlerCFGAccess::read(): Miss some configuration values of handler set!" );
218 for( nTarget
=0; nTarget
<nTargetCount
; ++nTarget
)
220 // create it new for every loop to guarantee a real empty object!
221 ProtocolHandler aHandler
;
222 aHandler
.m_sUNOName
= ::utl::extractFirstFromConfigurationPath(lNames
[nSource
]);
224 // unpack all values of this handler
225 css::uno::Sequence
< OUString
> lTemp
;
226 lValues
[nTarget
] >>= lTemp
;
227 aHandler
.m_lProtocols
= Converter::convert_seqOUString2OUStringList(lTemp
);
229 // register his pattern into the performance search hash
230 for (auto const& item
: aHandler
.m_lProtocols
)
232 rPatternHash
[item
] = lNames
[nSource
];
235 // insert the handler info into the normal handler cache
236 rHandlerHash
[lNames
[nSource
]] = aHandler
;
241 void HandlerCFGAccess::Notify(const css::uno::Sequence
< OUString
>& /*lPropertyNames*/)
243 HandlerHash aHandler
;
244 PatternHash aPattern
;
246 read(aHandler
, aPattern
);
248 m_pCache
->takeOver(std::move(aHandler
), std::move(aPattern
));
251 void HandlerCFGAccess::ImplCommit()
255 } // namespace framework
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */