29#include <osl/diagnose.h>
30#include <rtl/ustrbuf.hxx>
37#include <com/sun/star/ucb/ContentCreationException.hpp>
38#include <com/sun/star/uno/DeploymentException.hpp>
39#include <com/sun/star/lang/DisposedException.hpp>
40#include <com/sun/star/lang/IllegalArgumentException.hpp>
41#include <com/sun/star/lang/XServiceInfo.hpp>
42#include <com/sun/star/lang/XSingleComponentFactory.hpp>
43#include <com/sun/star/lang/XSingleServiceFactory.hpp>
44#include <com/sun/star/util/XUpdatable.hpp>
45#include <com/sun/star/container/XContentEnumerationAccess.hpp>
46#include <com/sun/star/deployment/XPackageTypeInfo.hpp>
47#include <com/sun/star/deployment/XPackageRegistry.hpp>
50#include <unordered_map>
51#include <unordered_set>
63typedef ::cppu::WeakComponentImplHelper<
64 deployment::XPackageRegistry, util::XUpdatable >
t_helper;
69 struct ci_string_hash {
70 std::size_t operator () ( OUString
const & str )
const {
71 return str.toAsciiLowerCase().hashCode();
74 struct ci_string_equals {
75 bool operator () ( std::u16string_view str1, std::u16string_view str2 )
const{
79 typedef std::unordered_map<
80 OUString, Reference<deployment::XPackageRegistry>,
81 ci_string_hash, ci_string_equals > t_string2registry;
82 typedef std::unordered_map<
84 ci_string_hash, ci_string_equals > t_string2string;
86 Reference<deployment::XPackageRegistry> > t_registryset;
92 std::vector< Reference<deployment::XPackageTypeInfo> >
m_typesInfos;
95 Reference<deployment::XPackageRegistry>
const & xBackend );
99 virtual void SAL_CALL disposing()
override;
101 virtual ~PackageRegistryImpl()
override;
106 static Reference<deployment::XPackageRegistry>
create(
107 OUString
const & context,
108 OUString
const & cachePath,
109 Reference<XComponentContext>
const & xComponentContext );
112 virtual void SAL_CALL
update()
override;
115 virtual Reference<deployment::XPackage> SAL_CALL bindPackage(
116 OUString
const & url, OUString
const & mediaType,
sal_Bool bRemoved,
117 OUString
const & identifier, Reference<XCommandEnvironment>
const & xCmdEnv )
override;
118 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
119 getSupportedPackageTypes()
override;
120 virtual void SAL_CALL packageRemoved(OUString
const & url, OUString
const & mediaType)
override;
125void PackageRegistryImpl::check()
127 ::osl::MutexGuard guard( m_aMutex );
128 if (rBHelper.bInDispose || rBHelper.bDisposed) {
129 throw lang::DisposedException(
130 "PackageRegistry instance has already been disposed!",
131 static_cast<OWeakObject *
>(
this) );
136void PackageRegistryImpl::disposing()
147 t_helper::disposing();
151PackageRegistryImpl::~PackageRegistryImpl()
156OUString normalizeMediaType( std::u16string_view mediaType )
166 return buf.makeStringAndClear();
170void PackageRegistryImpl::packageRemoved(
171 OUString
const & url, OUString
const & mediaType)
173 const t_string2registry::const_iterator
i =
178 i->second->packageRemoved(url, mediaType);
182void PackageRegistryImpl::insertBackend(
183 Reference<deployment::XPackageRegistry>
const & xBackend )
186 std::unordered_set<OUString> ambiguousFilters;
188 const Sequence< Reference<deployment::XPackageTypeInfo> > packageTypes(
189 xBackend->getSupportedPackageTypes() );
190 for ( Reference<deployment::XPackageTypeInfo>
const & xPackageType : packageTypes )
194 const OUString mediaType( normalizeMediaType(
195 xPackageType->getMediaType() ) );
196 std::pair<t_string2registry::iterator, bool> a_insertion(
198 if (a_insertion.second)
201 sal_Int32 semi = mediaType.indexOf(
';' );
205 const OUString fileFilter( xPackageType->getFileFilter() );
208 const bool bExtension = (mediaType ==
"application/vnd.sun.star.package-bundle");
209 if (fileFilter.isEmpty() || fileFilter ==
"*.*" || fileFilter ==
"*" || bExtension)
217 OUString token( fileFilter.getToken( 0,
';', nIndex ) );
218 if (token.match(
"*." ))
219 token = token.copy( 1 );
223 bool ambig = (token.indexOf(
'*') >= 0 ||
224 token.indexOf(
'?') >= 0);
226 std::pair<t_string2string::iterator, bool> ins(
228 token, mediaType ) );
233 const t_string2registry::const_iterator iFind(
236 ins.first->second ) );
246 ambiguousFilters.insert( token );
252#if OSL_DEBUG_LEVEL > 0
255 SAL_WARN(
"desktop",
"more than one PackageRegistryBackend for media-type=\""
258 << Reference<lang::XServiceInfo>(
266 for (
auto const& ambiguousFilter : ambiguousFilters)
274 OUString
const & context,
275 OUString
const & cachePath,
276 Reference<XComponentContext>
const & xComponentContext )
281 Reference<container::XEnumeration> xEnum(
282 Reference<container::XContentEnumerationAccess>(
283 xComponentContext->getServiceManager(),
284 UNO_QUERY_THROW )->createContentEnumeration(
285 "com.sun.star.deployment.PackageRegistryBackend" ) );
288 while (xEnum->hasMoreElements())
290 Any element( xEnum->nextElement() );
291 Sequence<Any> registryArgs(cachePath.isEmpty() ? 1 : 3 );
292 auto pregistryArgs = registryArgs.getArray();
293 pregistryArgs[ 0 ] <<= context;
294 if (!cachePath.isEmpty())
296 Reference<lang::XServiceInfo> xServiceInfo(
297 element, UNO_QUERY_THROW );
298 OUString registryCachePath(
301 xServiceInfo->getImplementationName(),
302 rtl_UriCharClassPchar,
303 rtl_UriEncodeIgnoreEscapes,
304 RTL_TEXTENCODING_UTF8 ) ) );
305 pregistryArgs[ 1 ] <<= registryCachePath;
306 pregistryArgs[ 2 ] <<=
false;
308 Reference<XCommandEnvironment>() );
311 Reference<deployment::XPackageRegistry> xBackend;
312 Reference<lang::XSingleComponentFactory> xFac( element, UNO_QUERY );
315 xFac->createInstanceWithArgumentsAndContext(
316 registryArgs, xComponentContext ), UNO_QUERY );
319 Reference<lang::XSingleServiceFactory> xSingleServiceFac(
320 element, UNO_QUERY_THROW );
322 xSingleServiceFac->createInstanceWithArguments(
323 registryArgs ), UNO_QUERY );
325 if (! xBackend.is()) {
326 throw DeploymentException(
327 "cannot instantiate PackageRegistryBackend service: "
328 + Reference<lang::XServiceInfo>(
330 static_cast<OWeakObject *
>(that.get()) );
333 that->insertBackend( xBackend );
341 Reference<deployment::XPackageRegistry> extensionBackend =
343 that, context, cachePath, xComponentContext);
344 that->insertBackend(extensionBackend);
346 Reference<lang::XServiceInfo> xServiceInfo(
347 extensionBackend, UNO_QUERY_THROW );
349 OSL_ASSERT(xServiceInfo.is());
350 OUString registryCachePath(
353 xServiceInfo->getImplementationName(),
354 rtl_UriCharClassPchar,
355 rtl_UriEncodeIgnoreEscapes,
356 RTL_TEXTENCODING_UTF8 ) ) );
357 create_folder(
nullptr, registryCachePath, Reference<XCommandEnvironment>());
360#if OSL_DEBUG_LEVEL > 0
363 t_registryset allBackends;
365 for (
auto const& elem : that->m_filter2mediaType)
367 const Reference<deployment::XPackageRegistry> xBackend(
368 that->m_mediaType2backend.find( elem.second )->second );
369 allBackends.insert( xBackend );
371 "extension \"" + elem.first +
"\" maps to media-type \"" + elem.second
372 +
"\" maps to backend "
373 + Reference<lang::XServiceInfo>(
374 xBackend, UNO_QUERY_THROW )
375 ->getImplementationName()
379 for (
auto const& ambiguousBackend : that->m_ambiguousBackends)
383 Reference<lang::XServiceInfo>(
386 const Sequence< Reference<deployment::XPackageTypeInfo> > types(
387 ambiguousBackend->getSupportedPackageTypes() );
388 for ( sal_Int32 pos = 0;
pos < types.getLength(); ++
pos ) {
389 Reference<deployment::XPackageTypeInfo>
const & xInfo =
391 buf.append( xInfo->getMediaType() );
392 const OUString
filter( xInfo->getFileFilter() );
394 buf.append(
" (" +
filter +
")" );
396 if (pos < (types.getLength() - 1))
401 allBackends.insert( that->m_ambiguousBackends.begin(),
402 that->m_ambiguousBackends.end() );
403 OSL_ASSERT( allBackends == that->m_allBackends );
417 const Reference<util::XUpdatable> xUpdatable(backend, UNO_QUERY);
419 xUpdatable->update();
425Reference<deployment::XPackage> PackageRegistryImpl::bindPackage(
426 OUString
const & url, OUString
const & mediaType_,
sal_Bool bRemoved,
427 OUString
const & identifier, Reference<XCommandEnvironment>
const & xCmdEnv )
430 OUString mediaType(mediaType_);
431 if (mediaType.isEmpty())
439 &ucbContent, url, xCmdEnv,
false )
442 catch (
const css::ucb::ContentCreationException&)
449 OUString title( StrTitle::getTitle( ucbContent ) );
452 const t_string2string::const_iterator iFind(
455 mediaType = iFind->second;
458 sal_Int32
point = title.indexOf(
'.', 1 );
461 title = title.copy(point);
465 if (mediaType.isEmpty())
471 return ambiguousBackend->bindPackage( url, mediaType, bRemoved,
472 identifier, xCmdEnv );
474 catch (
const lang::IllegalArgumentException &) {
477 throw lang::IllegalArgumentException(
478 DpResId(RID_STR_CANNOT_DETECT_MEDIA_TYPE) + url,
479 static_cast<OWeakObject *
>(
this),
static_cast<sal_Int16
>(-1) );
484 t_string2registry::const_iterator iFind(
488 sal_Int32 q = mediaType.indexOf(
';' );
493 mediaType.subView( 0, q ) ) );
497 throw lang::IllegalArgumentException(
498 DpResId(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType,
499 static_cast<OWeakObject *
>(
this),
static_cast<sal_Int16
>(-1) );
501 return iFind->second->bindPackage( url, mediaType, bRemoved,
502 identifier, xCmdEnv );
507Sequence< Reference<deployment::XPackageTypeInfo> >
508PackageRegistryImpl::getSupportedPackageTypes()
515Reference<deployment::XPackageRegistry>
create(
516 OUString
const & context,
517 OUString
const & cachePath,
518 Reference<XComponentContext>
const & xComponentContext )
521 context, cachePath, xComponentContext );
OUString DpResId(TranslateId aId)
t_registryset m_ambiguousBackends
t_string2registry m_mediaType2backend
std::vector< Reference< deployment::XPackageTypeInfo > > m_typesInfos
t_registryset m_allBackends
t_string2string m_filter2mediaType
#define SAL_WARN(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString getImplementationName()
OUString makeURL(std::u16string_view baseURL, OUString const &relPath_)
appends a relative path to a url.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_folder(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
void try_dispose(css::uno::Reference< css::uno::XInterface > const &x)
void TRACE(OUString const &sText)
print the text to the console in a debug build.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
css::uno::Reference< css::deployment::XPackageRegistry > create(OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Reference< deployment::XPackageRegistry > create(OUString const &context, OUString const &cachePath, Reference< XComponentContext > const &xComponentContext)
::cppu::WeakImplHelper< css::script::provider::XScriptProvider, css::script::browse::XBrowseNode, css::lang::XServiceInfo, css::lang::XInitialization, css::container::XNameContainer > t_helper
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)