Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / desktop / source / deployment / registry / component / dp_component.cxx
blobcbe7548f05cb194557155a50d53abbcec590341a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #include <strings.hrc>
22 #include <dp_misc.h>
23 #include <dp_shared.hxx>
24 #include <dp_backend.h>
25 #include <dp_platform.hxx>
26 #include <dp_ucb.h>
27 #include <rtl/string.hxx>
28 #include <rtl/strbuf.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <rtl/uri.hxx>
31 #include <sal/log.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <ucbhelper/content.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <utility>
37 #include <xmlscript/xml_helper.hxx>
38 #include <svl/inettype.hxx>
39 #include <comphelper/diagnose_ex.hxx>
40 #include <o3tl/string_view.hxx>
41 #include <com/sun/star/beans/NamedValue.hpp>
42 #include <com/sun/star/deployment/DeploymentException.hpp>
43 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
44 #include <com/sun/star/container/XNameContainer.hpp>
45 #include <com/sun/star/container/XSet.hpp>
46 #include <com/sun/star/registry/XSimpleRegistry.hpp>
47 #include <com/sun/star/registry/XImplementationRegistration.hpp>
48 #include <com/sun/star/loader/XImplementationLoader.hpp>
49 #include <com/sun/star/io/XInputStream.hpp>
50 #include <com/sun/star/ucb/NameClash.hpp>
51 #include <com/sun/star/util/theMacroExpander.hpp>
52 #include <algorithm>
53 #include <deque>
54 #include <memory>
55 #include <string_view>
56 #include <unordered_map>
57 #include <vector>
58 #include "dp_compbackenddb.hxx"
60 using namespace ::dp_misc;
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::ucb;
65 namespace dp_registry::backend::component {
66 namespace {
68 /** return a vector of bootstrap variables which have been provided
69 as command arguments.
71 std::vector<OUString> getCmdBootstrapVariables()
73 std::vector<OUString> ret;
74 sal_uInt32 count = osl_getCommandArgCount();
75 for (sal_uInt32 i = 0; i < count; i++)
77 OUString arg;
78 osl_getCommandArg(i, &arg.pData);
79 if (arg.startsWith("-env:"))
80 ret.push_back(arg);
82 return ret;
85 bool jarManifestHeaderPresent(
86 OUString const & url, std::u16string_view name,
87 Reference<XCommandEnvironment> const & xCmdEnv )
89 OUString buf = "vnd.sun.star.zip://"
90 + ::rtl::Uri::encode(
91 url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes,
92 RTL_TEXTENCODING_UTF8 )
93 + "/META-INF/MANIFEST.MF";
94 ::ucbhelper::Content manifestContent;
95 OUString line;
96 return
97 create_ucb_content(
98 &manifestContent, buf, xCmdEnv,
99 false /* no throw */ )
100 && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US );
104 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
106 class ComponentPackageImpl : public ::dp_registry::backend::Package
108 BackendImpl * getMyBackend() const;
110 const OUString m_loader;
112 enum class Reg { Uninit, Void, Registered, NotRegistered, MaybeRegistered };
113 Reg m_registered;
115 void getComponentInfo(
116 ComponentBackendDb::Data * data,
117 std::vector< css::uno::Reference< css::uno::XInterface > > *
118 factories,
119 Reference<XComponentContext> const & xContext );
121 void componentLiveInsertion(
122 ComponentBackendDb::Data const & data,
123 std::vector< css::uno::Reference< css::uno::XInterface > > const &
124 factories);
126 void componentLiveRemoval(ComponentBackendDb::Data const & data);
128 // Package
129 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
130 ::osl::ResettableMutexGuard & guard,
131 ::rtl::Reference<AbortChannel> const & abortChannel,
132 Reference<XCommandEnvironment> const & xCmdEnv ) override;
133 virtual void processPackage_(
134 ::osl::ResettableMutexGuard & guard,
135 bool registerPackage,
136 bool startup,
137 ::rtl::Reference<AbortChannel> const & abortChannel,
138 Reference<XCommandEnvironment> const & xCmdEnv ) override;
140 Reference<registry::XSimpleRegistry> getRDB() const;
142 public:
143 ComponentPackageImpl(
144 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
145 OUString const & url, OUString const & name,
146 Reference<deployment::XPackageTypeInfo> const & xPackageType,
147 OUString loader, bool bRemoved,
148 OUString const & identifier);
150 friend class ComponentPackageImpl;
152 class ComponentsPackageImpl : public ::dp_registry::backend::Package
154 BackendImpl * getMyBackend() const;
156 // Package
157 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
158 ::osl::ResettableMutexGuard & guard,
159 ::rtl::Reference<AbortChannel> const & abortChannel,
160 Reference<XCommandEnvironment> const & xCmdEnv ) override;
161 virtual void processPackage_(
162 ::osl::ResettableMutexGuard & guard,
163 bool registerPackage,
164 bool startup,
165 ::rtl::Reference<AbortChannel> const & abortChannel,
166 Reference<XCommandEnvironment> const & xCmdEnv ) override;
167 public:
168 ComponentsPackageImpl(
169 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
170 OUString const & url, OUString const & name,
171 Reference<deployment::XPackageTypeInfo> const & xPackageType,
172 bool bRemoved, OUString const & identifier);
174 friend class ComponentsPackageImpl;
176 class TypelibraryPackageImpl : public ::dp_registry::backend::Package
178 BackendImpl * getMyBackend() const;
180 const bool m_jarFile;
182 // Package
183 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
184 ::osl::ResettableMutexGuard & guard,
185 ::rtl::Reference<AbortChannel> const & abortChannel,
186 Reference<XCommandEnvironment> const & xCmdEnv ) override;
187 virtual void processPackage_(
188 ::osl::ResettableMutexGuard & guard,
189 bool registerPackage,
190 bool startup,
191 ::rtl::Reference<AbortChannel> const & abortChannel,
192 Reference<XCommandEnvironment> const & xCmdEnv ) override;
194 public:
195 TypelibraryPackageImpl(
196 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
197 OUString const & url, OUString const & name,
198 Reference<deployment::XPackageTypeInfo> const & xPackageType,
199 bool jarFile, bool bRemoved,
200 OUString const & identifier);
202 friend class TypelibraryPackageImpl;
204 /** Serves for unregistering packages that were registered on a
205 different platform. This can happen if one has remotely mounted
206 /home, for example.
208 class OtherPlatformPackageImpl : public ::dp_registry::backend::Package
210 public:
211 OtherPlatformPackageImpl(
212 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
213 OUString const & url, OUString const & name,
214 Reference<deployment::XPackageTypeInfo> const & xPackageType,
215 bool bRemoved, OUString const & identifier, OUString platform);
217 private:
218 BackendImpl * getMyBackend() const;
220 Reference<registry::XSimpleRegistry> impl_openRDB() const;
221 Reference<XInterface> impl_createInstance(OUString const& rService) const;
223 // Package
224 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
225 ::osl::ResettableMutexGuard & guard,
226 ::rtl::Reference<AbortChannel> const & abortChannel,
227 Reference<XCommandEnvironment> const & xCmdEnv ) override;
228 virtual void processPackage_(
229 ::osl::ResettableMutexGuard & guard,
230 bool registerPackage,
231 bool startup,
232 ::rtl::Reference<AbortChannel> const & abortChannel,
233 Reference<XCommandEnvironment> const & xCmdEnv ) override;
235 private:
236 OUString const m_aPlatform;
238 friend class OtherPlatformPackageImpl;
240 std::deque<OUString> m_jar_typelibs;
241 std::deque<OUString> m_rdb_typelibs;
242 std::deque<OUString> m_components;
244 enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS };
246 std::deque<OUString> & getRcItemList( RcItem kind ) {
247 switch (kind)
249 case RCITEM_JAR_TYPELIB:
250 return m_jar_typelibs;
251 case RCITEM_RDB_TYPELIB:
252 return m_rdb_typelibs;
253 default: // case RCITEM_COMPONENTS
254 return m_components;
258 bool m_unorc_inited;
259 bool m_unorc_modified;
260 bool bSwitchedRdbFiles;
262 typedef std::unordered_map< OUString, Reference<XInterface> > t_string2object;
263 t_string2object m_backendObjects;
265 // PackageRegistryBackend
266 virtual Reference<deployment::XPackage> bindPackage_(
267 OUString const & url, OUString const & mediaType,
268 bool bRemoved, OUString const & identifier,
269 Reference<XCommandEnvironment> const & xCmdEnv ) override;
271 virtual void SAL_CALL disposing() override;
273 const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo;
274 const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo;
275 const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo;
276 const Reference<deployment::XPackageTypeInfo> m_xComponentsTypeInfo;
277 const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo;
278 const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo;
279 Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
281 OUString m_commonRDB;
282 OUString m_nativeRDB;
284 //URLs of the original rdbs (before any switching):
285 OUString m_commonRDB_orig;
286 OUString m_nativeRDB_orig;
288 std::unique_ptr<ComponentBackendDb> m_backendDb;
290 void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data);
291 ComponentBackendDb::Data readDataFromDb(std::u16string_view url);
292 void revokeEntryFromDb(std::u16string_view url);
294 Reference<registry::XSimpleRegistry> m_xCommonRDB;
295 Reference<registry::XSimpleRegistry> m_xNativeRDB;
297 void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv );
298 void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv );
300 Reference<XInterface> getObject( OUString const & id );
301 Reference<XInterface> insertObject(
302 OUString const & id, Reference<XInterface> const & xObject );
303 void releaseObject( OUString const & id );
305 void addToUnoRc( RcItem kind, OUString const & url,
306 Reference<XCommandEnvironment> const & xCmdEnv );
307 void removeFromUnoRc( RcItem kind, OUString const & url,
308 Reference<XCommandEnvironment> const & xCmdEnv );
309 bool hasInUnoRc( RcItem kind, OUString const & url );
311 css::uno::Reference< css::uno::XComponentContext > getRootContext() const;
313 public:
314 BackendImpl( Sequence<Any> const & args,
315 Reference<XComponentContext> const & xComponentContext );
317 // XServiceInfo
318 virtual OUString SAL_CALL getImplementationName() override;
319 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
320 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
322 // XPackageRegistry
323 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
324 getSupportedPackageTypes() override;
326 virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
328 using PackageRegistryBackend::disposing;
330 //Will be called from ComponentPackageImpl
331 void initServiceRdbFiles();
335 BackendImpl::ComponentPackageImpl::ComponentPackageImpl(
336 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
337 OUString const & url, OUString const & name,
338 Reference<deployment::XPackageTypeInfo> const & xPackageType,
339 OUString loader, bool bRemoved,
340 OUString const & identifier)
341 : Package( myBackend, url, name, name /* display-name */,
342 xPackageType, bRemoved, identifier),
343 m_loader(std::move( loader )),
344 m_registered( Reg::Uninit )
347 Reference<registry::XSimpleRegistry>
348 BackendImpl::ComponentPackageImpl::getRDB() const
350 BackendImpl * that = getMyBackend();
352 //Late "initialization" of the services rdb files
353 //This is to prevent problems when running several
354 //instances of OOo with root rights in parallel. This
355 //would otherwise cause problems when copying the rdbs.
356 //See http://qa.openoffice.org/issues/show_bug.cgi?id=99257
358 const ::osl::MutexGuard guard( m_aMutex );
359 if (!that->bSwitchedRdbFiles)
361 that->bSwitchedRdbFiles = true;
362 that->initServiceRdbFiles();
365 if ( m_loader == "com.sun.star.loader.SharedLibrary" )
366 return that->m_xNativeRDB;
367 else
368 return that->m_xCommonRDB;
371 BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const
373 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
374 if (nullptr == pBackend)
376 //Throws a DisposedException
377 check();
378 //We should never get here...
379 throw RuntimeException(
380 "Failed to get the BackendImpl",
381 static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this)));
383 return pBackend;
387 void BackendImpl::disposing()
389 try {
390 m_backendObjects = t_string2object();
391 if (m_xNativeRDB.is()) {
392 m_xNativeRDB->close();
393 m_xNativeRDB.clear();
395 if (m_xCommonRDB.is()) {
396 m_xCommonRDB->close();
397 m_xCommonRDB.clear();
399 unorc_flush( Reference<XCommandEnvironment>() );
401 PackageRegistryBackend::disposing();
403 catch (const RuntimeException &) {
404 throw;
406 catch (const Exception &) {
407 Any exc( ::cppu::getCaughtException() );
408 throw lang::WrappedTargetRuntimeException(
409 "caught unexpected exception while disposing...",
410 static_cast<OWeakObject *>(this), exc );
415 void BackendImpl::initServiceRdbFiles()
417 const Reference<XCommandEnvironment> xCmdEnv;
419 ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv, m_xComponentContext );
420 ::ucbhelper::Content oldRDB;
421 // switch common rdb:
422 if (!m_commonRDB_orig.isEmpty())
424 (void)create_ucb_content(
425 &oldRDB, makeURL( getCachePath(), m_commonRDB_orig),
426 xCmdEnv, false /* no throw */ );
428 m_commonRDB = m_commonRDB_orig == "common.rdb" ? std::u16string_view(u"common_.rdb") : std::u16string_view(u"common.rdb");
429 if (oldRDB.get().is())
431 cacheDir.transferContent(
432 oldRDB, ::ucbhelper::InsertOperation::Copy,
433 m_commonRDB, NameClash::OVERWRITE );
434 oldRDB = ::ucbhelper::Content();
436 // switch native rdb:
437 if (!m_nativeRDB_orig.isEmpty())
439 (void)create_ucb_content(
440 &oldRDB, makeURL(getCachePath(), m_nativeRDB_orig),
441 xCmdEnv, false /* no throw */ );
443 const OUString plt_rdb( getPlatformString() + ".rdb" );
444 const OUString plt_rdb_( getPlatformString() + "_.rdb" );
445 m_nativeRDB = (m_nativeRDB_orig == plt_rdb ) ? plt_rdb_ : plt_rdb;
446 if (oldRDB.get().is())
448 cacheDir.transferContent(
449 oldRDB, ::ucbhelper::InsertOperation::Copy,
450 m_nativeRDB, NameClash::OVERWRITE );
453 // UNO is bootstrapped, flush for next process start:
454 m_unorc_modified = true;
455 unorc_flush( Reference<XCommandEnvironment>() );
458 // common rdb for java, native rdb for shared lib components
459 if (!m_commonRDB.isEmpty()) {
460 m_xCommonRDB.set(
461 m_xComponentContext->getServiceManager()
462 ->createInstanceWithContext(
463 "com.sun.star.registry.SimpleRegistry",
464 m_xComponentContext ), UNO_QUERY_THROW );
465 m_xCommonRDB->open(
466 makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ),
467 false, true);
469 if (!m_nativeRDB.isEmpty()) {
470 m_xNativeRDB.set(
471 m_xComponentContext->getServiceManager()
472 ->createInstanceWithContext(
473 "com.sun.star.registry.SimpleRegistry",
474 m_xComponentContext ), UNO_QUERY_THROW );
475 m_xNativeRDB->open(
476 makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ),
477 false, true);
481 BackendImpl::BackendImpl(
482 Sequence<Any> const & args,
483 Reference<XComponentContext> const & xComponentContext )
484 : PackageRegistryBackend( args, xComponentContext ),
485 m_unorc_inited( false ),
486 m_unorc_modified( false ),
487 bSwitchedRdbFiles(false),
488 m_xDynComponentTypeInfo( new Package::TypeInfo(
489 "application/vnd.sun.star.uno-component;type=native;platform=" +
490 getPlatformString(),
491 "*" SAL_DLLEXTENSION,
492 DpResId(RID_STR_DYN_COMPONENT)
493 ) ),
494 m_xJavaComponentTypeInfo( new Package::TypeInfo(
495 "application/vnd.sun.star.uno-component;type=Java",
496 "*.jar",
497 DpResId(RID_STR_JAVA_COMPONENT)
498 ) ),
499 m_xPythonComponentTypeInfo( new Package::TypeInfo(
500 "application/vnd.sun.star.uno-component;type=Python",
501 "*.py",
502 DpResId(
503 RID_STR_PYTHON_COMPONENT)
504 ) ),
505 m_xComponentsTypeInfo( new Package::TypeInfo(
506 "application/vnd.sun.star.uno-components",
507 "*.components",
508 DpResId(RID_STR_COMPONENTS)
509 ) ),
510 m_xRDBTypelibTypeInfo( new Package::TypeInfo(
511 "application/vnd.sun.star.uno-typelibrary;type=RDB",
512 "*.rdb",
513 DpResId(RID_STR_RDB_TYPELIB)
514 ) ),
515 m_xJavaTypelibTypeInfo( new Package::TypeInfo(
516 "application/vnd.sun.star.uno-typelibrary;type=Java",
517 "*.jar",
518 DpResId(RID_STR_JAVA_TYPELIB)
519 ) ),
520 m_typeInfos{ m_xDynComponentTypeInfo, m_xJavaComponentTypeInfo, m_xPythonComponentTypeInfo,
521 m_xComponentsTypeInfo, m_xRDBTypelibTypeInfo, m_xJavaTypelibTypeInfo }
523 const Reference<XCommandEnvironment> xCmdEnv;
525 if (transientMode())
527 // in-mem rdbs:
528 // common rdb for java, native rdb for shared lib components
529 m_xCommonRDB.set(
530 xComponentContext->getServiceManager()->createInstanceWithContext(
531 "com.sun.star.registry.SimpleRegistry",
532 xComponentContext ), UNO_QUERY_THROW );
533 m_xCommonRDB->open( OUString() /* in-mem */,
534 false /* ! read-only */, true /* create */ );
535 m_xNativeRDB.set(
536 xComponentContext->getServiceManager()->createInstanceWithContext(
537 "com.sun.star.registry.SimpleRegistry",
538 xComponentContext ), UNO_QUERY_THROW );
539 m_xNativeRDB->open( OUString() /* in-mem */,
540 false /* ! read-only */, true /* create */ );
542 else
544 unorc_verify_init( xCmdEnv );
545 OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
546 m_backendDb.reset(
547 new ComponentBackendDb(getComponentContext(), dbFile));
551 // XServiceInfo
552 OUString BackendImpl::getImplementationName()
554 return "com.sun.star.comp.deployment.component.PackageRegistryBackend";
557 sal_Bool BackendImpl::supportsService( const OUString& ServiceName )
559 return cppu::supportsService(this, ServiceName);
562 css::uno::Sequence< OUString > BackendImpl::getSupportedServiceNames()
564 return { BACKEND_SERVICE_NAME };
567 void BackendImpl::addDataToDb(
568 OUString const & url, ComponentBackendDb::Data const & data)
570 if (m_backendDb)
571 m_backendDb->addEntry(url, data);
574 ComponentBackendDb::Data BackendImpl::readDataFromDb(std::u16string_view url)
576 ComponentBackendDb::Data data;
577 if (m_backendDb)
578 data = m_backendDb->getEntry(url);
579 return data;
582 void BackendImpl::revokeEntryFromDb(std::u16string_view url)
584 if (m_backendDb)
585 m_backendDb->revokeEntry(url);
588 // XPackageRegistry
590 Sequence< Reference<deployment::XPackageTypeInfo> >
591 BackendImpl::getSupportedPackageTypes()
593 return m_typeInfos;
596 void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
598 if (m_backendDb)
599 m_backendDb->removeEntry(url);
602 // PackageRegistryBackend
604 Reference<deployment::XPackage> BackendImpl::bindPackage_(
605 OUString const & url, OUString const & mediaType_,
606 bool bRemoved, OUString const & identifier,
607 Reference<XCommandEnvironment> const & xCmdEnv )
609 OUString mediaType(mediaType_);
610 if ( mediaType.isEmpty() || mediaType == "application/vnd.sun.star.uno-component" || mediaType == "application/vnd.sun.star.uno-typelibrary" )
612 // detect exact media-type:
613 ::ucbhelper::Content ucbContent;
614 if (create_ucb_content( &ucbContent, url, xCmdEnv )) {
615 const OUString title( StrTitle::getTitle( ucbContent ) );
616 if (title.endsWithIgnoreAsciiCase(SAL_DLLEXTENSION))
618 mediaType = "application/vnd.sun.star.uno-component;type=native;platform=" +
619 getPlatformString();
621 else if (title.endsWithIgnoreAsciiCase(".jar"))
623 if (jarManifestHeaderPresent(
624 url, u"RegistrationClassName", xCmdEnv ))
625 mediaType = "application/vnd.sun.star.uno-component;type=Java";
626 if (mediaType.isEmpty())
627 mediaType = "application/vnd.sun.star.uno-typelibrary;type=Java";
629 else if (title.endsWithIgnoreAsciiCase(".py"))
630 mediaType = "application/vnd.sun.star.uno-component;type=Python";
631 else if (title.endsWithIgnoreAsciiCase(".rdb"))
632 mediaType = "application/vnd.sun.star.uno-typelibrary;type=RDB";
634 if (mediaType.isEmpty())
635 throw lang::IllegalArgumentException(
636 StrCannotDetectMediaType() + url,
637 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
640 OUString type, subType;
641 INetContentTypeParameterList params;
642 if (INetContentTypes::parse( mediaType, type, subType, &params ))
644 if (type.equalsIgnoreAsciiCase("application"))
646 OUString name;
647 if (!bRemoved)
649 ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
650 name = StrTitle::getTitle( ucbContent );
653 if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-component"))
655 // xxx todo: probe and evaluate component xml description
657 auto const iter = params.find(OString("platform"));
658 bool bPlatformFits(iter == params.end());
659 OUString aPlatform;
660 if (!bPlatformFits) // platform is specified, we have to check
662 aPlatform = iter->second.m_sValue;
663 bPlatformFits = platform_fits(aPlatform);
665 // If the package is being removed, do not care whether
666 // platform fits. We won't be using it anyway.
667 if (bPlatformFits || bRemoved) {
668 auto const iterType = params.find(OString("type"));
669 if (iterType != params.end())
671 OUString const & value = iterType->second.m_sValue;
672 if (value.equalsIgnoreAsciiCase("native")) {
673 if (bPlatformFits)
674 return new BackendImpl::ComponentPackageImpl(
675 this, url, name, m_xDynComponentTypeInfo,
676 "com.sun.star.loader.SharedLibrary",
677 bRemoved, identifier);
678 else
679 return new BackendImpl::OtherPlatformPackageImpl(
680 this, url, name, m_xDynComponentTypeInfo,
681 bRemoved, identifier, aPlatform);
683 if (value.equalsIgnoreAsciiCase("Java")) {
684 return new BackendImpl::ComponentPackageImpl(
685 this, url, name, m_xJavaComponentTypeInfo,
686 "com.sun.star.loader.Java2",
687 bRemoved, identifier);
689 if (value.equalsIgnoreAsciiCase("Python")) {
690 return new BackendImpl::ComponentPackageImpl(
691 this, url, name, m_xPythonComponentTypeInfo,
692 "com.sun.star.loader.Python",
693 bRemoved, identifier);
698 else if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-components"))
700 auto const iter = params.find(OString("platform"));
701 if (iter == params.end() || platform_fits(iter->second.m_sValue)) {
702 return new BackendImpl::ComponentsPackageImpl(
703 this, url, name, m_xComponentsTypeInfo, bRemoved,
704 identifier);
707 else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-typelibrary"))
709 auto const iter = params.find(OString("type"));
710 if (iter != params.end()) {
711 OUString const & value = iter->second.m_sValue;
712 if (value.equalsIgnoreAsciiCase("RDB"))
714 return new BackendImpl::TypelibraryPackageImpl(
715 this, url, name, m_xRDBTypelibTypeInfo,
716 false /* rdb */, bRemoved, identifier);
718 if (value.equalsIgnoreAsciiCase("Java")) {
719 return new BackendImpl::TypelibraryPackageImpl(
720 this, url, name, m_xJavaTypelibTypeInfo,
721 true /* jar */, bRemoved, identifier);
727 throw lang::IllegalArgumentException(
728 StrUnsupportedMediaType() + mediaType,
729 static_cast<OWeakObject *>(this),
730 static_cast<sal_Int16>(-1) );
734 void BackendImpl::unorc_verify_init(
735 Reference<XCommandEnvironment> const & xCmdEnv )
737 if (transientMode())
738 return;
739 const ::osl::MutexGuard guard( m_aMutex );
740 if ( m_unorc_inited)
741 return;
743 // common rc:
744 ::ucbhelper::Content ucb_content;
745 if (create_ucb_content(
746 &ucb_content,
747 makeURL( getCachePath(), "unorc" ),
748 xCmdEnv, false /* no throw */ ))
750 OUString line;
751 if (readLine( &line, u"UNO_JAVA_CLASSPATH=", ucb_content,
752 RTL_TEXTENCODING_UTF8 ))
754 sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1;
755 do {
756 OUString token( o3tl::trim(o3tl::getToken(line, 0, ' ', index )) );
757 if (!token.isEmpty())
759 if (create_ucb_content(
760 nullptr, expandUnoRcTerm(token), xCmdEnv,
761 false /* no throw */ ))
763 //The jar file may not exist anymore if a shared or bundled
764 //extension was removed, but it can still be in the unorc
765 //After running XExtensionManager::synchronize, the unorc is
766 //cleaned up
767 m_jar_typelibs.push_back( token );
771 while (index >= 0);
773 if (readLine( &line, u"UNO_TYPES=", ucb_content,
774 RTL_TEXTENCODING_UTF8 )) {
775 sal_Int32 index = sizeof ("UNO_TYPES=") - 1;
776 do {
777 OUString token( o3tl::trim(o3tl::getToken(line, 0, ' ', index )) );
778 if (!token.isEmpty())
780 if (token[ 0 ] == '?')
781 token = token.copy( 1 );
782 if (create_ucb_content(
783 nullptr, expandUnoRcTerm(token), xCmdEnv,
784 false /* no throw */ ))
786 //The RDB file may not exist anymore if a shared or bundled
787 //extension was removed, but it can still be in the unorc.
788 //After running XExtensionManager::synchronize, the unorc is
789 //cleaned up
790 m_rdb_typelibs.push_back( token );
794 while (index >= 0);
796 if (readLine( &line, u"UNO_SERVICES=", ucb_content,
797 RTL_TEXTENCODING_UTF8 ))
799 // The UNO_SERVICES line always has the BNF form
800 // "UNO_SERVICES="
801 // ("?$ORIGIN/" <common-rdb>)? -- first
802 // "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}"? -- second
803 // ("?" ("BUNDLED_EXTENSIONS" | -- third
804 // "UNO_SHARED_PACKAGES_CACHE" | "UNO_USER_PACKAGES_CACHE")
805 // ...)*
806 // so can unambiguously be split into its three parts:
807 int state = 1;
808 for (sal_Int32 i = RTL_CONSTASCII_LENGTH("UNO_SERVICES=");
809 i >= 0;)
811 OUString token(line.getToken(0, ' ', i));
812 if (!token.isEmpty())
814 if (state == 1 && token.match("?$ORIGIN/"))
816 m_commonRDB_orig = token.copy(
817 RTL_CONSTASCII_LENGTH("?$ORIGIN/"));
818 state = 2;
820 else if ( state <= 2 && token == "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" )
822 state = 3;
824 else
826 if (token[0] == '?')
828 token = token.copy(1);
830 m_components.push_back(token);
831 state = 3;
837 // native rc:
838 if (create_ucb_content(
839 &ucb_content,
840 makeURL( getCachePath(), getPlatformString() + "rc"),
841 xCmdEnv, false /* no throw */ )) {
842 if (readLine( &line, u"UNO_SERVICES=", ucb_content,
843 RTL_TEXTENCODING_UTF8 )) {
844 m_nativeRDB_orig = line.copy(
845 sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 );
849 m_unorc_modified = false;
850 m_unorc_inited = true;
854 void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv )
856 if (transientMode())
857 return;
858 if (!m_unorc_inited || !m_unorc_modified)
859 return;
861 OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
862 OString osOrigin = OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
863 OStringBuffer buf("ORIGIN=" + osOrigin + OStringChar(LF));
865 if (! m_jar_typelibs.empty())
867 auto iPos( m_jar_typelibs.cbegin() );
868 auto const iEnd( m_jar_typelibs.cend() );
869 buf.append( "UNO_JAVA_CLASSPATH=" );
870 while (iPos != iEnd) {
871 // encoded ASCII file-urls:
872 const OString item(
873 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
874 buf.append( item );
875 ++iPos;
876 if (iPos != iEnd)
877 buf.append( ' ' );
879 buf.append(LF);
881 if (! m_rdb_typelibs.empty())
883 auto iPos( m_rdb_typelibs.cbegin() );
884 auto const iEnd( m_rdb_typelibs.cend() );
885 buf.append( "UNO_TYPES=" );
886 while (iPos != iEnd) {
887 buf.append( '?' );
888 // encoded ASCII file-urls:
889 const OString item(
890 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
891 buf.append( item );
892 ++iPos;
893 if (iPos != iEnd)
894 buf.append( ' ' );
896 buf.append(LF);
899 // If we duplicated the common or native rdb then we must use those urls
900 //otherwise we use those of the original files. That is, m_commonRDB_orig
901 //and m_nativeRDB_orig;
902 OUString sCommonRDB(m_commonRDB.isEmpty() ? m_commonRDB_orig : m_commonRDB );
903 OUString sNativeRDB(m_nativeRDB.isEmpty() ? m_nativeRDB_orig : m_nativeRDB );
905 if (!sCommonRDB.isEmpty() || !sNativeRDB.isEmpty() ||
906 !m_components.empty())
908 buf.append( "UNO_SERVICES=" );
909 bool space = false;
910 if (!sCommonRDB.isEmpty())
912 buf.append( "?$ORIGIN/"
913 + OUStringToOString( sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
914 space = true;
916 if (!sNativeRDB.isEmpty())
918 if (space)
920 buf.append(' ');
922 buf.append( "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" );
923 space = true;
925 // write native rc:
926 OString buf2 =
927 "ORIGIN=" +
928 osOrigin +
929 OStringChar(LF) +
930 "UNO_SERVICES=?$ORIGIN/" +
931 OUStringToOString( sNativeRDB, RTL_TEXTENCODING_ASCII_US ) +
932 OStringChar(LF);
934 const Reference<io::XInputStream> xData(
935 ::xmlscript::createInputStream(
936 reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
937 buf2.getLength() ) );
938 ::ucbhelper::Content ucb_content(
939 makeURL( getCachePath(), getPlatformString() + "rc" ),
940 xCmdEnv, m_xComponentContext );
941 ucb_content.writeStream( xData, true /* replace existing */ );
943 for (auto const& component : m_components)
945 if (space)
947 buf.append(' ');
949 buf.append("?" + OUStringToOString(component, RTL_TEXTENCODING_UTF8));
950 space = true;
952 buf.append(LF);
955 // write unorc:
956 const Reference<io::XInputStream> xData(
957 ::xmlscript::createInputStream(
958 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
959 buf.getLength() ) );
960 ::ucbhelper::Content ucb_content(
961 makeURL( getCachePath(), "unorc" ), xCmdEnv, m_xComponentContext );
962 ucb_content.writeStream( xData, true /* replace existing */ );
964 m_unorc_modified = false;
968 void BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
969 Reference<XCommandEnvironment> const & xCmdEnv )
971 const OUString rcterm( dp_misc::makeRcTerm(url_) );
972 const ::osl::MutexGuard guard( m_aMutex );
973 unorc_verify_init( xCmdEnv );
974 std::deque<OUString> & rSet = getRcItemList(kind);
975 if (std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
976 rSet.push_front( rcterm ); // prepend to list, thus overriding
977 // write immediately:
978 m_unorc_modified = true;
979 unorc_flush( xCmdEnv );
984 void BackendImpl::removeFromUnoRc(
985 RcItem kind, OUString const & url_,
986 Reference<XCommandEnvironment> const & xCmdEnv )
988 const OUString rcterm( dp_misc::makeRcTerm(url_) );
989 const ::osl::MutexGuard guard( m_aMutex );
990 unorc_verify_init( xCmdEnv );
991 std::deque<OUString> & aRcItemList = getRcItemList(kind);
992 aRcItemList.erase(std::remove(aRcItemList.begin(), aRcItemList.end(), rcterm), aRcItemList.end());
993 // write immediately:
994 m_unorc_modified = true;
995 unorc_flush( xCmdEnv );
999 bool BackendImpl::hasInUnoRc(
1000 RcItem kind, OUString const & url_ )
1002 const OUString rcterm( dp_misc::makeRcTerm(url_) );
1003 const ::osl::MutexGuard guard( m_aMutex );
1004 std::deque<OUString> const & rSet = getRcItemList(kind);
1005 return std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1008 css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext()
1009 const
1011 css::uno::Reference< css::uno::XComponentContext > rootContext(
1012 getComponentContext()->getValueByName("_root"),
1013 css::uno::UNO_QUERY);
1014 return rootContext.is() ? rootContext : getComponentContext();
1018 void BackendImpl::releaseObject( OUString const & id )
1020 const ::osl::MutexGuard guard( m_aMutex );
1021 m_backendObjects.erase( id );
1025 Reference<XInterface> BackendImpl::getObject( OUString const & id )
1027 const ::osl::MutexGuard guard( m_aMutex );
1028 const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1029 if (iFind == m_backendObjects.end())
1030 return Reference<XInterface>();
1031 else
1032 return iFind->second;
1036 Reference<XInterface> BackendImpl::insertObject(
1037 OUString const & id, Reference<XInterface> const & xObject )
1039 const ::osl::MutexGuard guard( m_aMutex );
1040 const std::pair<t_string2object::iterator, bool> insertion(
1041 m_backendObjects.emplace( id, xObject ) );
1042 return insertion.first->second;
1046 Reference<XComponentContext> raise_uno_process(
1047 Reference<XComponentContext> const & xContext,
1048 ::rtl::Reference<AbortChannel> const & abortChannel )
1050 OSL_ASSERT( xContext.is() );
1052 OUString url( util::theMacroExpander::get(xContext)->expandMacros( "$URE_BIN_DIR/uno" ) );
1054 const OUString connectStr = "uno:pipe,name=" + generateRandomPipeId() + ";urp;uno.ComponentContext";
1056 // raise core UNO process to register/run a component,
1057 // javavm service uses unorc next to executable to retrieve deployed
1058 // jar typelibs
1060 std::vector<OUString> args{
1061 #if OSL_DEBUG_LEVEL == 0
1062 "--quiet",
1063 #endif
1064 "--singleaccept",
1065 "-u",
1066 connectStr,
1067 // don't inherit from unorc:
1068 "-env:INIFILENAME=" };
1070 //now add the bootstrap variables which were supplied on the command line
1071 std::vector<OUString> bootvars = getCmdBootstrapVariables();
1072 args.insert(args.end(), bootvars.begin(), bootvars.end());
1074 oslProcess hProcess;
1075 try {
1076 hProcess = raiseProcess(
1077 url, comphelper::containerToSequence(args) );
1079 catch (...) {
1080 OUStringBuffer sMsg = "error starting process: " + url;
1081 for(const auto& arg : args)
1082 sMsg.append(" " + arg);
1083 throw uno::RuntimeException(sMsg.makeStringAndClear());
1085 try {
1086 return Reference<XComponentContext>(
1087 resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1088 UNO_QUERY_THROW );
1090 catch (...) {
1091 // try to terminate process:
1092 if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1094 OSL_ASSERT( false );
1096 throw;
1100 void extractComponentData(
1101 css::uno::Reference< css::uno::XComponentContext > const & context,
1102 css::uno::Reference< css::registry::XRegistryKey > const & registry,
1103 ComponentBackendDb::Data * data,
1104 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1105 css::uno::Reference< css::loader::XImplementationLoader > const &
1106 componentLoader,
1107 OUString const & componentUrl)
1109 OSL_ASSERT(
1110 context.is() && registry.is() && data != nullptr && componentLoader.is());
1111 OUString registryName(registry->getKeyName());
1112 sal_Int32 prefix = registryName.getLength();
1113 if (!registryName.endsWith("/")) {
1114 prefix += RTL_CONSTASCII_LENGTH("/");
1116 const css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1117 keys(registry->openKeys());
1118 css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1119 context->getServiceManager(), css::uno::UNO_SET_THROW);
1120 for (css::uno::Reference< css::registry::XRegistryKey > const & key : keys) {
1121 OUString name(key->getKeyName().copy(prefix));
1122 data->implementationNames.push_back(name);
1123 css::uno::Reference< css::registry::XRegistryKey > singletons(
1124 key->openKey("UNO/SINGLETONS"));
1125 if (singletons.is()) {
1126 sal_Int32 prefix2 = key->getKeyName().getLength() +
1127 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1128 const css::uno::Sequence<
1129 css::uno::Reference< css::registry::XRegistryKey > >
1130 singletonKeys(singletons->openKeys());
1131 for (css::uno::Reference< css::registry::XRegistryKey > const & singletonKey : singletonKeys) {
1132 data->singletons.emplace_back(
1133 singletonKey->getKeyName().copy(prefix2), name);
1136 if (factories != nullptr) {
1137 factories->push_back(
1138 componentLoader->activate(
1139 name, OUString(), componentUrl, key));
1144 void BackendImpl::ComponentPackageImpl::getComponentInfo(
1145 ComponentBackendDb::Data * data,
1146 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1147 Reference<XComponentContext> const & xContext )
1149 const Reference<loader::XImplementationLoader> xLoader(
1150 xContext->getServiceManager()->createInstanceWithContext(
1151 m_loader, xContext ), UNO_QUERY );
1152 if (! xLoader.is())
1154 throw css::deployment::DeploymentException(
1155 "cannot instantiate loader " + m_loader,
1156 static_cast< OWeakObject * >(this), Any());
1159 // HACK: highly dependent on stoc/source/servicemanager
1160 // and stoc/source/implreg implementation which rely on the same
1161 // services.rdb format!
1162 // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1163 // writeRegistryInfo, however, but are known, fixed values here, so
1164 // can be passed into extractComponentData
1165 OUString url(getURL());
1166 const Reference<registry::XSimpleRegistry> xMemReg(
1167 xContext->getServiceManager()->createInstanceWithContext(
1168 "com.sun.star.registry.SimpleRegistry", xContext ),
1169 UNO_QUERY_THROW );
1170 xMemReg->open( OUString() /* in mem */, false, true );
1171 xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1172 extractComponentData(
1173 xContext, xMemReg->getRootKey(), data, factories, xLoader, url);
1176 void BackendImpl::ComponentPackageImpl::componentLiveInsertion(
1177 ComponentBackendDb::Data const & data,
1178 std::vector< css::uno::Reference< css::uno::XInterface > > const &
1179 factories)
1181 css::uno::Reference< css::uno::XComponentContext > rootContext(
1182 getMyBackend()->getRootContext());
1183 css::uno::Reference< css::container::XSet > set(
1184 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1185 std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1186 factory(factories.begin());
1187 for (auto const& implementationName : data.implementationNames)
1189 try {
1190 set->insert(css::uno::Any(*factory++));
1191 } catch (const container::ElementExistException &) {
1192 SAL_WARN("desktop.deployment", "implementation already registered " << implementationName);
1195 if (data.singletons.empty()) return;
1197 css::uno::Reference< css::container::XNameContainer > cont(
1198 rootContext, css::uno::UNO_QUERY_THROW);
1199 for (auto const& singleton : data.singletons)
1201 OUString name("/singletons/" + singleton.first);
1202 //TODO: Update should be atomic:
1203 try {
1204 cont->removeByName( name + "/arguments");
1205 } catch (const container::NoSuchElementException &) {}
1206 try {
1207 cont->insertByName( name + "/service", css::uno::Any(singleton.second));
1208 } catch (const container::ElementExistException &) {
1209 cont->replaceByName( name + "/service", css::uno::Any(singleton.second));
1211 try {
1212 cont->insertByName(name, css::uno::Any());
1213 } catch (const container::ElementExistException &) {
1214 SAL_WARN("desktop.deployment", "singleton already registered " << singleton.first);
1215 cont->replaceByName(name, css::uno::Any());
1220 void BackendImpl::ComponentPackageImpl::componentLiveRemoval(
1221 ComponentBackendDb::Data const & data)
1223 css::uno::Reference< css::uno::XComponentContext > rootContext(
1224 getMyBackend()->getRootContext());
1225 css::uno::Reference< css::container::XSet > set(
1226 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1227 for (auto const& implementationName : data.implementationNames)
1229 try {
1230 set->remove(css::uno::Any(implementationName));
1231 } catch (const css::container::NoSuchElementException &) {
1232 // ignore if factory has not been live deployed
1235 if (data.singletons.empty())
1236 return;
1238 css::uno::Reference< css::container::XNameContainer > cont(
1239 rootContext, css::uno::UNO_QUERY_THROW);
1240 for (auto const& singleton : data.singletons)
1242 OUString name("/singletons/" + singleton.first);
1243 //TODO: Removal should be atomic:
1244 try {
1245 cont->removeByName(name);
1246 } catch (const container::NoSuchElementException &) {}
1247 try {
1248 cont->removeByName( name + "/service" );
1249 } catch (const container::NoSuchElementException &) {}
1250 try {
1251 cont->removeByName( name + "/arguments" );
1252 } catch (const container::NoSuchElementException &) {}
1256 // Package
1258 //We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1259 //And it also shows the problem if another extension has overwritten an implementation
1260 //entry, because it contains the same service implementation
1261 beans::Optional< beans::Ambiguous<sal_Bool> >
1262 BackendImpl::ComponentPackageImpl::isRegistered_(
1263 ::osl::ResettableMutexGuard &,
1264 ::rtl::Reference<AbortChannel> const & abortChannel,
1265 Reference<XCommandEnvironment> const & )
1267 if (m_registered == Reg::Uninit)
1269 m_registered = Reg::NotRegistered;
1270 const Reference<registry::XSimpleRegistry> xRDB( getRDB() );
1271 if (xRDB.is())
1273 bool bAmbiguousComponentName = false;
1274 // lookup rdb for location URL:
1275 const Reference<registry::XRegistryKey> xRootKey(
1276 xRDB->getRootKey() );
1277 const Reference<registry::XRegistryKey> xImplKey(
1278 xRootKey->openKey( "IMPLEMENTATIONS" ) );
1279 Sequence<OUString> implNames;
1280 if (xImplKey.is() && xImplKey->isValid())
1281 implNames = xImplKey->getKeyNames();
1282 OUString const * pImplNames = implNames.getConstArray();
1283 sal_Int32 pos = implNames.getLength();
1284 for ( ; pos--; )
1286 checkAborted( abortChannel );
1287 const OUString key(
1288 pImplNames[ pos ] + "/UNO/LOCATION" );
1289 const Reference<registry::XRegistryKey> xKey(
1290 xRootKey->openKey(key) );
1291 if (xKey.is() && xKey->isValid())
1293 const OUString location( xKey->getAsciiValue() );
1294 if (location.equalsIgnoreAsciiCase( getURL() ))
1296 break;
1298 else
1300 //try to match only the file name
1301 OUString thisUrl(getURL());
1302 std::u16string_view thisFileName(thisUrl.subView(thisUrl.lastIndexOf('/')));
1304 std::u16string_view locationFileName(location.subView(location.lastIndexOf('/')));
1305 if (o3tl::equalsIgnoreAsciiCase(locationFileName, thisFileName))
1306 bAmbiguousComponentName = true;
1310 if (pos >= 0)
1311 m_registered = Reg::Registered;
1312 else if (bAmbiguousComponentName)
1313 m_registered = Reg::MaybeRegistered;
1317 //Different extensions can use the same service implementations. Then the extensions
1318 //which was installed last will overwrite the one from the other extension. That is
1319 //the registry will contain the path (the location) of the library or jar of the
1320 //second extension. In this case isRegistered called for the lib of the first extension
1321 //would return "not registered". That would mean that during uninstallation
1322 //XPackage::registerPackage is not called, because it just was not registered. This is,
1323 //however, necessary for jar files. Registering and unregistering update
1324 //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1325 //Therefore, we will return always "is ambiguous" if the path of this component cannot
1326 //be found in the registry and if there is another path and both have the same file name (but
1327 //the rest of the path is different).
1328 //If the caller cannot precisely determine that this package was registered, then it must
1329 //call registerPackage.
1330 bool bAmbiguous = m_registered == Reg::Void // Reg::Void == we are in the progress of unregistration
1331 || m_registered == Reg::MaybeRegistered;
1332 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1333 true /* IsPresent */,
1334 beans::Ambiguous<sal_Bool>(
1335 m_registered == Reg::Registered, bAmbiguous) );
1339 void BackendImpl::ComponentPackageImpl::processPackage_(
1340 ::osl::ResettableMutexGuard &,
1341 bool doRegisterPackage,
1342 bool startup,
1343 ::rtl::Reference<AbortChannel> const & abortChannel,
1344 Reference<XCommandEnvironment> const & xCmdEnv )
1346 BackendImpl * that = getMyBackend();
1347 OUString url(getURL());
1348 if (doRegisterPackage) {
1349 ComponentBackendDb::Data data;
1350 css::uno::Reference< css::uno::XComponentContext > context;
1351 if (startup) {
1352 context = that->getComponentContext();
1353 } else {
1354 context.set(that->getObject(url), css::uno::UNO_QUERY);
1355 if (!context.is()) {
1356 context.set(
1357 that->insertObject(
1358 url,
1359 raise_uno_process(
1360 that->getComponentContext(), abortChannel)),
1361 css::uno::UNO_QUERY_THROW);
1364 css::uno::Reference< css::registry::XImplementationRegistration> impreg(
1365 context->getServiceManager()->createInstanceWithContext(
1366 "com.sun.star.registry.ImplementationRegistration",
1367 context),
1368 css::uno::UNO_QUERY_THROW);
1369 css::uno::Reference< css::registry::XSimpleRegistry > rdb(getRDB());
1370 impreg->registerImplementation(m_loader, url, rdb);
1371 // Only write to unorc after successful registration; it may fail if
1372 // there is no suitable java
1373 if (m_loader == "com.sun.star.loader.Java2" && !jarManifestHeaderPresent(url, u"UNO-Type-Path", xCmdEnv))
1375 that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1376 data.javaTypeLibrary = true;
1378 std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1379 getComponentInfo(&data, startup ? nullptr : &factories, context);
1380 if (!startup) {
1381 try {
1382 componentLiveInsertion(data, factories);
1383 } catch (css::uno::Exception &) {
1384 TOOLS_INFO_EXCEPTION("desktop.deployment", "caught");
1385 try {
1386 impreg->revokeImplementation(url, rdb);
1387 } catch (css::uno::RuntimeException &) {
1388 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignored");
1390 throw;
1393 m_registered = Reg::Registered;
1394 that->addDataToDb(url, data);
1395 } else { // revoke
1396 m_registered = Reg::Void;
1397 ComponentBackendDb::Data data(that->readDataFromDb(url));
1398 css::uno::Reference< css::uno::XComponentContext > context(
1399 that->getObject(url), css::uno::UNO_QUERY);
1400 bool remoteContext = context.is();
1401 if (!remoteContext) {
1402 context = that->getComponentContext();
1404 if (!startup) {
1405 componentLiveRemoval(data);
1407 css::uno::Reference< css::registry::XImplementationRegistration >(
1408 context->getServiceManager()->createInstanceWithContext(
1409 "com.sun.star.registry.ImplementationRegistration",
1410 context),
1411 css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1412 if (data.javaTypeLibrary) {
1413 that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1415 if (remoteContext) {
1416 that->releaseObject(url);
1418 m_registered = Reg::NotRegistered;
1419 getMyBackend()->revokeEntryFromDb(url);
1423 BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1424 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1425 OUString const & url, OUString const & name,
1426 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1427 bool jarFile, bool bRemoved, OUString const & identifier)
1428 : Package( myBackend, url, name, name /* display-name */,
1429 xPackageType, bRemoved, identifier),
1430 m_jarFile( jarFile )
1434 // Package
1435 BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1437 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1438 if (nullptr == pBackend)
1440 //May throw a DisposedException
1441 check();
1442 //We should never get here...
1443 throw RuntimeException( "Failed to get the BackendImpl",
1444 static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1446 return pBackend;
1449 beans::Optional< beans::Ambiguous<sal_Bool> >
1450 BackendImpl::TypelibraryPackageImpl::isRegistered_(
1451 ::osl::ResettableMutexGuard &,
1452 ::rtl::Reference<AbortChannel> const &,
1453 Reference<XCommandEnvironment> const & )
1455 BackendImpl * that = getMyBackend();
1456 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1457 true /* IsPresent */,
1458 beans::Ambiguous<sal_Bool>(
1459 that->hasInUnoRc(
1460 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1461 false /* IsAmbiguous */ ) );
1465 void BackendImpl::TypelibraryPackageImpl::processPackage_(
1466 ::osl::ResettableMutexGuard &,
1467 bool doRegisterPackage,
1468 bool /*startup*/,
1469 ::rtl::Reference<AbortChannel> const &,
1470 Reference<XCommandEnvironment> const & xCmdEnv )
1472 BackendImpl * that = getMyBackend();
1473 const OUString url( getURL() );
1475 if (doRegisterPackage)
1477 // live insertion:
1478 if (m_jarFile) {
1479 // xxx todo add to classpath at runtime: ???
1480 //SB: It is probably not worth it to add the live inserted type
1481 // library JAR to the UnoClassLoader in the soffice process. Any
1482 // live inserted component JAR that might reference this type
1483 // library JAR runs in its own uno process, so there is probably no
1484 // Java code in the soffice process that would see any UNO types
1485 // introduced by this type library JAR.
1487 else // RDB:
1489 css::uno::Reference< css::container::XSet >(
1490 that->getComponentContext()->getValueByName(
1491 "/singletons"
1492 "/com.sun.star.reflection.theTypeDescriptionManager"),
1493 css::uno::UNO_QUERY_THROW)->insert(
1494 css::uno::Any(expandUnoRcUrl(url)));
1497 that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1498 url, xCmdEnv );
1500 else // revokePackage()
1502 that->removeFromUnoRc(
1503 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1505 // revoking types at runtime, possible, sensible?
1506 if (!m_jarFile) {
1507 css::uno::Reference< css::container::XSet >(
1508 that->getComponentContext()->getValueByName(
1509 "/singletons"
1510 "/com.sun.star.reflection.theTypeDescriptionManager"),
1511 css::uno::UNO_QUERY_THROW)->remove(
1512 css::uno::Any(expandUnoRcUrl(url)));
1517 BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl(
1518 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1519 OUString const & url, OUString const & name,
1520 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1521 bool bRemoved, OUString const & identifier, OUString platform)
1522 : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier)
1523 , m_aPlatform(std::move(platform))
1525 OSL_PRECOND(bRemoved, "this class can only be used for removing packages!");
1528 BackendImpl *
1529 BackendImpl::OtherPlatformPackageImpl::getMyBackend() const
1531 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1532 if (nullptr == pBackend)
1534 //Throws a DisposedException
1535 check();
1536 //We should never get here...
1537 throw RuntimeException("Failed to get the BackendImpl",
1538 static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this)));
1540 return pBackend;
1543 Reference<registry::XSimpleRegistry>
1544 BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const
1546 OUString const aRDB(m_aPlatform + ".rdb");
1547 OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB));
1549 Reference<registry::XSimpleRegistry> xRegistry;
1553 xRegistry.set(
1554 impl_createInstance("com.sun.star.registry.SimpleRegistry"),
1555 UNO_QUERY)
1557 if (xRegistry.is())
1558 xRegistry->open(expandUnoRcUrl(aRDBPath), false, false);
1560 catch (registry::InvalidRegistryException const&)
1562 // If the registry does not exist, we do not need to bother at all
1563 xRegistry.set(nullptr);
1566 SAL_WARN_IF( !xRegistry.is(), "desktop.deployment", "could not create registry for the package's platform");
1567 return xRegistry;
1570 Reference<XInterface>
1571 BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService)
1572 const
1574 Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext());
1575 OSL_ASSERT(xContext.is());
1576 Reference<XInterface> xService;
1577 if (xContext.is())
1578 xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext));
1579 return xService;
1582 beans::Optional<beans::Ambiguous<sal_Bool> >
1583 BackendImpl::OtherPlatformPackageImpl::isRegistered_(
1584 ::osl::ResettableMutexGuard& /* guard */,
1585 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1586 Reference<XCommandEnvironment> const& /* xCmdEnv */ )
1588 return beans::Optional<beans::Ambiguous<sal_Bool> >(true,
1589 beans::Ambiguous<sal_Bool>(true, false));
1592 void
1593 BackendImpl::OtherPlatformPackageImpl::processPackage_(
1594 ::osl::ResettableMutexGuard& /* guard */,
1595 bool bRegisterPackage,
1596 bool /* bStartup */,
1597 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1598 Reference<XCommandEnvironment> const& /* xCmdEnv */)
1600 OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!");
1602 OUString const aURL(getURL());
1604 Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB());
1605 Reference<registry::XImplementationRegistration> const xImplReg(
1606 impl_createInstance("com.sun.star.registry.ImplementationRegistration"),
1607 UNO_QUERY)
1609 if (xImplReg.is() && xServicesRDB.is())
1610 xImplReg->revokeImplementation(aURL, xServicesRDB);
1611 if (xServicesRDB.is())
1612 xServicesRDB->close();
1614 getMyBackend()->revokeEntryFromDb(aURL);
1617 BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1619 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1620 if (nullptr == pBackend)
1622 //Throws a DisposedException
1623 check();
1624 //We should never get here...
1625 throw RuntimeException("Failed to get the BackendImpl",
1626 static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1628 return pBackend;
1631 beans::Optional< beans::Ambiguous<sal_Bool> >
1632 BackendImpl::ComponentsPackageImpl::isRegistered_(
1633 ::osl::ResettableMutexGuard &,
1634 ::rtl::Reference<AbortChannel> const &,
1635 Reference<XCommandEnvironment> const & )
1637 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1638 true,
1639 beans::Ambiguous<sal_Bool>(
1640 getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1643 void BackendImpl::ComponentsPackageImpl::processPackage_(
1644 ::osl::ResettableMutexGuard &,
1645 bool doRegisterPackage,
1646 bool startup,
1647 ::rtl::Reference<AbortChannel> const & abortChannel,
1648 Reference<XCommandEnvironment> const & xCmdEnv )
1650 BackendImpl * that = getMyBackend();
1651 OUString url(getURL());
1652 if (doRegisterPackage) {
1653 if (!startup) {
1654 css::uno::Reference< css::uno::XComponentContext > context(
1655 that->getObject(url), css::uno::UNO_QUERY);
1656 if (!context.is()) {
1657 context.set(
1658 that->insertObject(
1659 url,
1660 raise_uno_process(
1661 that->getComponentContext(), abortChannel)),
1662 css::uno::UNO_QUERY_THROW);
1664 // This relies on the root component context's service manager
1665 // supporting the extended XSet semantics:
1666 css::uno::Sequence< css::beans::NamedValue > args
1668 { "uri", css::uno::Any(expandUnoRcUrl(url)) },
1669 { "component-context", css::uno::Any(context) }
1671 css::uno::Reference< css::container::XSet > smgr(
1672 that->getRootContext()->getServiceManager(),
1673 css::uno::UNO_QUERY_THROW);
1674 smgr->insert(css::uno::Any(args));
1676 that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1677 } else { // revoke
1678 that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1679 if (!startup) {
1680 // This relies on the root component context's service manager
1681 // supporting the extended XSet semantics:
1682 css::uno::Sequence< css::beans::NamedValue > args { { "uri", css::uno::Any(expandUnoRcUrl(url)) } };
1683 css::uno::Reference< css::container::XSet > smgr(
1684 that->getRootContext()->getServiceManager(),
1685 css::uno::UNO_QUERY_THROW);
1686 smgr->remove(css::uno::Any(args));
1688 that->releaseObject(url);
1689 that->revokeEntryFromDb(url); // in case it got added with old code
1693 BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1694 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1695 OUString const & url, OUString const & name,
1696 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1697 bool bRemoved, OUString const & identifier)
1698 : Package( myBackend, url, name, name /* display-name */,
1699 xPackageType, bRemoved, identifier)
1702 } // anon namespace
1704 } // namespace dp_registry
1707 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1708 com_sun_star_comp_deployment_component_PackageRegistryBackend_get_implementation(
1709 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
1711 return cppu::acquire(new dp_registry::backend::component::BackendImpl(args, context));
1714 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */