25 #include <strings.hrc>
29 #include <osl/diagnose.h>
30 #include <rtl/ustrbuf.hxx>
31 #include <rtl/uri.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>
49 #include <string_view>
50 #include <unordered_map>
51 #include <unordered_set>
63 typedef ::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;
102 PackageRegistryImpl() : t_helper(
m_aMutex ) {}
106 static Reference<deployment::XPackageRegistry>
create(
107 OUString
const & context,
108 OUString
const & cachePath,
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,
118 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
119 getSupportedPackageTypes()
override;
120 virtual void SAL_CALL packageRemoved(OUString
const & url, OUString
const & mediaType)
override;
125 void 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) );
136 void PackageRegistryImpl::disposing()
145 m_allBackends = t_registryset();
147 t_helper::disposing();
151 PackageRegistryImpl::~PackageRegistryImpl()
156 OUString normalizeMediaType( std::u16string_view mediaType )
166 return buf.makeStringAndClear();
170 void PackageRegistryImpl::packageRemoved(
171 OUString
const & url, OUString
const & mediaType)
173 const t_string2registry::const_iterator
i =
178 i->second->packageRemoved(url, mediaType);
182 void 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,
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;
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 ) ) );
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() );
398 if (pos < (types.getLength() - 1))
403 allBackends.insert( that->m_ambiguousBackends.begin(),
404 that->m_ambiguousBackends.end() );
405 OSL_ASSERT( allBackends == that->m_allBackends );
419 const Reference<util::XUpdatable> xUpdatable(backend, UNO_QUERY);
421 xUpdatable->update();
427 Reference<deployment::XPackage> PackageRegistryImpl::bindPackage(
428 OUString
const & url, OUString
const & mediaType_,
sal_Bool bRemoved,
432 OUString mediaType(mediaType_);
433 if (mediaType.isEmpty())
441 &ucbContent, url, xCmdEnv,
false )
444 catch (
const css::ucb::ContentCreationException&)
451 OUString title( StrTitle::getTitle( ucbContent ) );
454 const t_string2string::const_iterator iFind(
457 mediaType = iFind->second;
460 sal_Int32
point = title.indexOf(
'.', 1 );
463 title = title.copy(point);
467 if (mediaType.isEmpty())
473 return ambiguousBackend->bindPackage( url, mediaType, bRemoved,
474 identifier, xCmdEnv );
476 catch (
const lang::IllegalArgumentException &) {
479 throw lang::IllegalArgumentException(
480 DpResId(RID_STR_CANNOT_DETECT_MEDIA_TYPE) + url,
481 static_cast<OWeakObject *>(
this), static_cast<sal_Int16>(-1) );
486 t_string2registry::const_iterator iFind(
490 sal_Int32 q = mediaType.indexOf(
';' );
495 mediaType.subView( 0, q ) ) );
499 throw lang::IllegalArgumentException(
500 DpResId(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType,
501 static_cast<OWeakObject *>(
this), static_cast<sal_Int16>(-1) );
503 return iFind->second->bindPackage( url, mediaType, bRemoved,
504 identifier, xCmdEnv );
509 Sequence< Reference<deployment::XPackageTypeInfo> >
510 PackageRegistryImpl::getSupportedPackageTypes()
517 Reference<deployment::XPackageRegistry>
create(
518 OUString
const & context,
519 OUString
const & cachePath,
523 context, cachePath, xComponentContext );
t_registryset m_allBackends
OUString getImplementationName()
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
OUString makeURL(OUString const &baseURL, OUString const &relPath_)
appends a relative path to a url.
std::vector< Reference< deployment::XPackageTypeInfo > > m_typesInfos
::cppu::WeakImplHelper< css::script::provider::XScriptProvider, css::script::browse::XBrowseNode, css::lang::XServiceInfo, css::lang::XInitialization, css::container::XNameContainer > t_helper
t_string2string m_filter2mediaType
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)
void TRACE(OUString const &sText)
print the text to the console in a debug build.
void try_dispose(css::uno::Reference< css::uno::XInterface > const &x)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
std::u16string_view trim(std::u16string_view str)
#define SAL_WARN(area, stream)
t_string2registry m_mediaType2backend
OUString DpResId(TranslateId aId)
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)
t_registryset m_ambiguousBackends
Reference< deployment::XPackageRegistry > create(OUString const &context, OUString const &cachePath, Reference< XComponentContext > const &xComponentContext)
css::uno::Reference< css::deployment::XPackageRegistry > create(OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)