Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / desktop / source / deployment / registry / component / dp_component.cxx
blob064fd9645f2fd7b83f23dea37f6936a1102a38a9
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_shared.hxx>
23 #include <dp_backend.h>
24 #include <dp_platform.hxx>
25 #include <dp_services.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 <ucbhelper/content.hxx>
34 #include <comphelper/servicedecl.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <xmlscript/xml_helper.hxx>
37 #include <svl/inettype.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <com/sun/star/deployment/DeploymentException.hpp>
40 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/container/XSet.hpp>
43 #include <com/sun/star/registry/XSimpleRegistry.hpp>
44 #include <com/sun/star/registry/XImplementationRegistration.hpp>
45 #include <com/sun/star/loader/XImplementationLoader.hpp>
46 #include <com/sun/star/io/XInputStream.hpp>
47 #include <com/sun/star/ucb/NameClash.hpp>
48 #include <com/sun/star/util/theMacroExpander.hpp>
49 #include <algorithm>
50 #include <deque>
51 #include <memory>
52 #include <unordered_map>
53 #include <vector>
54 #include "dp_compbackenddb.hxx"
56 using namespace ::dp_misc;
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::ucb;
61 namespace dp_registry {
62 namespace backend {
63 namespace component {
64 namespace {
66 #define IMPLEMENTATION_NAME "com.sun.star.comp.deployment.component.PackageRegistryBackend"
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, OUString const & name,
87 Reference<XCommandEnvironment> const & xCmdEnv )
89 OUStringBuffer buf;
90 buf.append( "vnd.sun.star.zip://" );
91 buf.append(
92 ::rtl::Uri::encode(
93 url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes,
94 RTL_TEXTENCODING_UTF8 ) );
95 buf.append( "/META-INF/MANIFEST.MF" );
96 ::ucbhelper::Content manifestContent;
97 OUString line;
98 return
99 create_ucb_content(
100 &manifestContent, buf.makeStringAndClear(), xCmdEnv,
101 false /* no throw */ )
102 && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US );
106 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
108 class ComponentPackageImpl : public ::dp_registry::backend::Package
110 BackendImpl * getMyBackend() const;
112 const OUString m_loader;
114 enum reg {
115 REG_UNINIT, REG_VOID, REG_REGISTERED, REG_NOT_REGISTERED, REG_MAYBE_REGISTERED
116 } m_registered;
118 void getComponentInfo(
119 ComponentBackendDb::Data * data,
120 std::vector< css::uno::Reference< css::uno::XInterface > > *
121 factories,
122 Reference<XComponentContext> const & xContext );
124 void componentLiveInsertion(
125 ComponentBackendDb::Data const & data,
126 std::vector< css::uno::Reference< css::uno::XInterface > > const &
127 factories);
129 void componentLiveRemoval(ComponentBackendDb::Data const & data);
131 // Package
132 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
133 ::osl::ResettableMutexGuard & guard,
134 ::rtl::Reference<AbortChannel> const & abortChannel,
135 Reference<XCommandEnvironment> const & xCmdEnv ) override;
136 virtual void processPackage_(
137 ::osl::ResettableMutexGuard & guard,
138 bool registerPackage,
139 bool startup,
140 ::rtl::Reference<AbortChannel> const & abortChannel,
141 Reference<XCommandEnvironment> const & xCmdEnv ) override;
143 Reference<registry::XSimpleRegistry> getRDB() const;
145 public:
146 ComponentPackageImpl(
147 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
148 OUString const & url, OUString const & name,
149 Reference<deployment::XPackageTypeInfo> const & xPackageType,
150 OUString const & loader, bool bRemoved,
151 OUString const & identifier);
153 friend class ComponentPackageImpl;
155 class ComponentsPackageImpl : public ::dp_registry::backend::Package
157 BackendImpl * getMyBackend() const;
159 // Package
160 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
161 ::osl::ResettableMutexGuard & guard,
162 ::rtl::Reference<AbortChannel> const & abortChannel,
163 Reference<XCommandEnvironment> const & xCmdEnv ) override;
164 virtual void processPackage_(
165 ::osl::ResettableMutexGuard & guard,
166 bool registerPackage,
167 bool startup,
168 ::rtl::Reference<AbortChannel> const & abortChannel,
169 Reference<XCommandEnvironment> const & xCmdEnv ) override;
170 public:
171 ComponentsPackageImpl(
172 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
173 OUString const & url, OUString const & name,
174 Reference<deployment::XPackageTypeInfo> const & xPackageType,
175 bool bRemoved, OUString const & identifier);
177 friend class ComponentsPackageImpl;
179 class TypelibraryPackageImpl : public ::dp_registry::backend::Package
181 BackendImpl * getMyBackend() const;
183 const bool m_jarFile;
185 // Package
186 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
187 ::osl::ResettableMutexGuard & guard,
188 ::rtl::Reference<AbortChannel> const & abortChannel,
189 Reference<XCommandEnvironment> const & xCmdEnv ) override;
190 virtual void processPackage_(
191 ::osl::ResettableMutexGuard & guard,
192 bool registerPackage,
193 bool startup,
194 ::rtl::Reference<AbortChannel> const & abortChannel,
195 Reference<XCommandEnvironment> const & xCmdEnv ) override;
197 public:
198 TypelibraryPackageImpl(
199 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
200 OUString const & url, OUString const & name,
201 Reference<deployment::XPackageTypeInfo> const & xPackageType,
202 bool jarFile, bool bRemoved,
203 OUString const & identifier);
205 friend class TypelibraryPackageImpl;
207 /** Serves for unregistering packages that were registered on a
208 different platform. This can happen if one has remotely mounted
209 /home, for example.
211 class OtherPlatformPackageImpl : public ::dp_registry::backend::Package
213 public:
214 OtherPlatformPackageImpl(
215 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
216 OUString const & url, OUString const & name,
217 Reference<deployment::XPackageTypeInfo> const & xPackageType,
218 bool bRemoved, OUString const & identifier, OUString const& rPlatform);
220 private:
221 BackendImpl * getMyBackend() const;
223 Reference<registry::XSimpleRegistry> impl_openRDB() const;
224 Reference<XInterface> impl_createInstance(OUString const& rService) const;
226 // Package
227 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
228 ::osl::ResettableMutexGuard & guard,
229 ::rtl::Reference<AbortChannel> const & abortChannel,
230 Reference<XCommandEnvironment> const & xCmdEnv ) override;
231 virtual void processPackage_(
232 ::osl::ResettableMutexGuard & guard,
233 bool registerPackage,
234 bool startup,
235 ::rtl::Reference<AbortChannel> const & abortChannel,
236 Reference<XCommandEnvironment> const & xCmdEnv ) override;
238 private:
239 OUString const m_aPlatform;
241 friend class OtherPlatformPackageImpl;
243 std::deque<OUString> m_jar_typelibs;
244 std::deque<OUString> m_rdb_typelibs;
245 std::deque<OUString> m_components;
247 enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS };
249 std::deque<OUString> & getRcItemList( RcItem kind ) {
250 switch (kind)
252 case RCITEM_JAR_TYPELIB:
253 return m_jar_typelibs;
254 case RCITEM_RDB_TYPELIB:
255 return m_rdb_typelibs;
256 default: // case RCITEM_COMPONENTS
257 return m_components;
261 bool m_unorc_inited;
262 bool m_unorc_modified;
263 bool bSwitchedRdbFiles;
265 typedef std::unordered_map< OUString, Reference<XInterface> > t_string2object;
266 t_string2object m_backendObjects;
268 // PackageRegistryBackend
269 virtual Reference<deployment::XPackage> bindPackage_(
270 OUString const & url, OUString const & mediaType,
271 bool bRemoved, OUString const & identifier,
272 Reference<XCommandEnvironment> const & xCmdEnv ) override;
274 virtual void SAL_CALL disposing() override;
276 const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo;
277 const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo;
278 const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo;
279 const Reference<deployment::XPackageTypeInfo> m_xComponentsTypeInfo;
280 const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo;
281 const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo;
282 Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
284 OUString m_commonRDB;
285 OUString m_nativeRDB;
287 //URLs of the original rdbs (before any switching):
288 OUString m_commonRDB_orig;
289 OUString m_nativeRDB_orig;
291 std::unique_ptr<ComponentBackendDb> m_backendDb;
293 void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data);
294 ComponentBackendDb::Data readDataFromDb(OUString const & url);
295 void revokeEntryFromDb(OUString const & url);
297 Reference<registry::XSimpleRegistry> m_xCommonRDB;
298 Reference<registry::XSimpleRegistry> m_xNativeRDB;
300 void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv );
301 void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv );
303 Reference<XInterface> getObject( OUString const & id );
304 Reference<XInterface> insertObject(
305 OUString const & id, Reference<XInterface> const & xObject );
306 void releaseObject( OUString const & id );
308 void addToUnoRc( RcItem kind, OUString const & url,
309 Reference<XCommandEnvironment> const & xCmdEnv );
310 void removeFromUnoRc( RcItem kind, OUString const & url,
311 Reference<XCommandEnvironment> const & xCmdEnv );
312 bool hasInUnoRc( RcItem kind, OUString const & url );
314 css::uno::Reference< css::uno::XComponentContext > getRootContext() const;
316 public:
317 BackendImpl( Sequence<Any> const & args,
318 Reference<XComponentContext> const & xComponentContext );
320 // XPackageRegistry
321 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
322 getSupportedPackageTypes() override;
324 virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
326 using PackageRegistryBackend::disposing;
328 //Will be called from ComponentPackageImpl
329 void initServiceRdbFiles();
333 BackendImpl::ComponentPackageImpl::ComponentPackageImpl(
334 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
335 OUString const & url, OUString const & name,
336 Reference<deployment::XPackageTypeInfo> const & xPackageType,
337 OUString const & loader, bool bRemoved,
338 OUString const & identifier)
339 : Package( myBackend, url, name, name /* display-name */,
340 xPackageType, bRemoved, identifier),
341 m_loader( loader ),
342 m_registered( REG_UNINIT )
345 Reference<registry::XSimpleRegistry>
346 BackendImpl::ComponentPackageImpl::getRDB() const
348 BackendImpl * that = getMyBackend();
350 //Late "initialization" of the services rdb files
351 //This is to prevent problems when running several
352 //instances of OOo with root rights in parallel. This
353 //would otherwise cause problems when copying the rdbs.
354 //See http://qa.openoffice.org/issues/show_bug.cgi?id=99257
356 const ::osl::MutexGuard guard( getMutex() );
357 if (!that->bSwitchedRdbFiles)
359 that->bSwitchedRdbFiles = true;
360 that->initServiceRdbFiles();
363 if ( m_loader == "com.sun.star.loader.SharedLibrary" )
364 return that->m_xNativeRDB;
365 else
366 return that->m_xCommonRDB;
369 BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const
371 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
372 if (nullptr == pBackend)
374 //Throws a DisposedException
375 check();
376 //We should never get here...
377 throw RuntimeException(
378 "Failed to get the BackendImpl",
379 static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this)));
381 return pBackend;
385 void BackendImpl::disposing()
387 try {
388 m_backendObjects = t_string2object();
389 if (m_xNativeRDB.is()) {
390 m_xNativeRDB->close();
391 m_xNativeRDB.clear();
393 if (m_xCommonRDB.is()) {
394 m_xCommonRDB->close();
395 m_xCommonRDB.clear();
397 unorc_flush( Reference<XCommandEnvironment>() );
399 PackageRegistryBackend::disposing();
401 catch (const RuntimeException &) {
402 throw;
404 catch (const Exception &) {
405 Any exc( ::cppu::getCaughtException() );
406 throw lang::WrappedTargetRuntimeException(
407 "caught unexpected exception while disposing...",
408 static_cast<OWeakObject *>(this), exc );
413 void BackendImpl::initServiceRdbFiles()
415 const Reference<XCommandEnvironment> xCmdEnv;
417 ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv, m_xComponentContext );
418 ::ucbhelper::Content oldRDB;
419 // switch common rdb:
420 if (!m_commonRDB_orig.isEmpty())
422 (void)create_ucb_content(
423 &oldRDB, makeURL( getCachePath(), m_commonRDB_orig),
424 xCmdEnv, false /* no throw */ );
426 m_commonRDB = m_commonRDB_orig == "common.rdb" ? OUStringLiteral("common_.rdb") : OUStringLiteral("common.rdb");
427 if (oldRDB.get().is())
429 cacheDir.transferContent(
430 oldRDB, ::ucbhelper::InsertOperation::Copy,
431 m_commonRDB, NameClash::OVERWRITE );
432 oldRDB = ::ucbhelper::Content();
434 // switch native rdb:
435 if (!m_nativeRDB_orig.isEmpty())
437 (void)create_ucb_content(
438 &oldRDB, makeURL(getCachePath(), m_nativeRDB_orig),
439 xCmdEnv, false /* no throw */ );
441 const OUString plt_rdb( getPlatformString() + ".rdb" );
442 const OUString plt_rdb_( getPlatformString() + "_.rdb" );
443 m_nativeRDB = (m_nativeRDB_orig == plt_rdb ) ? plt_rdb_ : plt_rdb;
444 if (oldRDB.get().is())
446 cacheDir.transferContent(
447 oldRDB, ::ucbhelper::InsertOperation::Copy,
448 m_nativeRDB, NameClash::OVERWRITE );
451 // UNO is bootstrapped, flush for next process start:
452 m_unorc_modified = true;
453 unorc_flush( Reference<XCommandEnvironment>() );
456 // common rdb for java, native rdb for shared lib components
457 if (!m_commonRDB.isEmpty()) {
458 m_xCommonRDB.set(
459 m_xComponentContext->getServiceManager()
460 ->createInstanceWithContext(
461 "com.sun.star.registry.SimpleRegistry",
462 m_xComponentContext ), UNO_QUERY_THROW );
463 m_xCommonRDB->open(
464 makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ),
465 false, true);
467 if (!m_nativeRDB.isEmpty()) {
468 m_xNativeRDB.set(
469 m_xComponentContext->getServiceManager()
470 ->createInstanceWithContext(
471 "com.sun.star.registry.SimpleRegistry",
472 m_xComponentContext ), UNO_QUERY_THROW );
473 m_xNativeRDB->open(
474 makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ),
475 false, true);
479 BackendImpl::BackendImpl(
480 Sequence<Any> const & args,
481 Reference<XComponentContext> const & xComponentContext )
482 : PackageRegistryBackend( args, xComponentContext ),
483 m_unorc_inited( false ),
484 m_unorc_modified( false ),
485 bSwitchedRdbFiles(false),
486 m_xDynComponentTypeInfo( new Package::TypeInfo(
487 "application/vnd.sun.star.uno-component;type=native;platform=" +
488 getPlatformString(),
489 "*" SAL_DLLEXTENSION,
490 DpResId(RID_STR_DYN_COMPONENT)
491 ) ),
492 m_xJavaComponentTypeInfo( new Package::TypeInfo(
493 "application/vnd.sun.star.uno-component;type=Java",
494 "*.jar",
495 DpResId(RID_STR_JAVA_COMPONENT)
496 ) ),
497 m_xPythonComponentTypeInfo( new Package::TypeInfo(
498 "application/vnd.sun.star.uno-component;type=Python",
499 "*.py",
500 DpResId(
501 RID_STR_PYTHON_COMPONENT)
502 ) ),
503 m_xComponentsTypeInfo( new Package::TypeInfo(
504 "application/vnd.sun.star.uno-components",
505 "*.components",
506 DpResId(RID_STR_COMPONENTS)
507 ) ),
508 m_xRDBTypelibTypeInfo( new Package::TypeInfo(
509 "application/vnd.sun.star.uno-typelibrary;type=RDB",
510 "*.rdb",
511 DpResId(RID_STR_RDB_TYPELIB)
512 ) ),
513 m_xJavaTypelibTypeInfo( new Package::TypeInfo(
514 "application/vnd.sun.star.uno-typelibrary;type=Java",
515 "*.jar",
516 DpResId(RID_STR_JAVA_TYPELIB)
517 ) ),
518 m_typeInfos( 6 )
520 m_typeInfos[ 0 ] = m_xDynComponentTypeInfo;
521 m_typeInfos[ 1 ] = m_xJavaComponentTypeInfo;
522 m_typeInfos[ 2 ] = m_xPythonComponentTypeInfo;
523 m_typeInfos[ 3 ] = m_xComponentsTypeInfo;
524 m_typeInfos[ 4 ] = m_xRDBTypelibTypeInfo;
525 m_typeInfos[ 5 ] = m_xJavaTypelibTypeInfo;
527 const Reference<XCommandEnvironment> xCmdEnv;
529 if (transientMode())
531 // in-mem rdbs:
532 // common rdb for java, native rdb for shared lib components
533 m_xCommonRDB.set(
534 xComponentContext->getServiceManager()->createInstanceWithContext(
535 "com.sun.star.registry.SimpleRegistry",
536 xComponentContext ), UNO_QUERY_THROW );
537 m_xCommonRDB->open( OUString() /* in-mem */,
538 false /* ! read-only */, true /* create */ );
539 m_xNativeRDB.set(
540 xComponentContext->getServiceManager()->createInstanceWithContext(
541 "com.sun.star.registry.SimpleRegistry",
542 xComponentContext ), UNO_QUERY_THROW );
543 m_xNativeRDB->open( OUString() /* in-mem */,
544 false /* ! read-only */, true /* create */ );
546 else
548 unorc_verify_init( xCmdEnv );
549 OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
550 m_backendDb.reset(
551 new ComponentBackendDb(getComponentContext(), dbFile));
555 void BackendImpl::addDataToDb(
556 OUString const & url, ComponentBackendDb::Data const & data)
558 if (m_backendDb)
559 m_backendDb->addEntry(url, data);
562 ComponentBackendDb::Data BackendImpl::readDataFromDb(OUString const & url)
564 ComponentBackendDb::Data data;
565 if (m_backendDb)
566 data = m_backendDb->getEntry(url);
567 return data;
570 void BackendImpl::revokeEntryFromDb(OUString const & url)
572 if (m_backendDb)
573 m_backendDb->revokeEntry(url);
576 // XPackageRegistry
578 Sequence< Reference<deployment::XPackageTypeInfo> >
579 BackendImpl::getSupportedPackageTypes()
581 return m_typeInfos;
584 void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
586 if (m_backendDb)
587 m_backendDb->removeEntry(url);
590 // PackageRegistryBackend
592 Reference<deployment::XPackage> BackendImpl::bindPackage_(
593 OUString const & url, OUString const & mediaType_,
594 bool bRemoved, OUString const & identifier,
595 Reference<XCommandEnvironment> const & xCmdEnv )
597 OUString mediaType(mediaType_);
598 if ( mediaType.isEmpty() || mediaType == "application/vnd.sun.star.uno-component" || mediaType == "application/vnd.sun.star.uno-typelibrary" )
600 // detect exact media-type:
601 ::ucbhelper::Content ucbContent;
602 if (create_ucb_content( &ucbContent, url, xCmdEnv )) {
603 const OUString title( StrTitle::getTitle( ucbContent ) );
604 if (title.endsWithIgnoreAsciiCase(SAL_DLLEXTENSION))
606 mediaType = "application/vnd.sun.star.uno-component;type=native;platform=" +
607 getPlatformString();
609 else if (title.endsWithIgnoreAsciiCase(".jar"))
611 if (jarManifestHeaderPresent(
612 url, "RegistrationClassName", xCmdEnv ))
613 mediaType = "application/vnd.sun.star.uno-component;type=Java";
614 if (mediaType.isEmpty())
615 mediaType = "application/vnd.sun.star.uno-typelibrary;type=Java";
617 else if (title.endsWithIgnoreAsciiCase(".py"))
618 mediaType = "application/vnd.sun.star.uno-component;type=Python";
619 else if (title.endsWithIgnoreAsciiCase(".rdb"))
620 mediaType = "application/vnd.sun.star.uno-typelibrary;type=RDB";
622 if (mediaType.isEmpty())
623 throw lang::IllegalArgumentException(
624 StrCannotDetectMediaType() + url,
625 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
628 OUString type, subType;
629 INetContentTypeParameterList params;
630 if (INetContentTypes::parse( mediaType, type, subType, &params ))
632 if (type.equalsIgnoreAsciiCase("application"))
634 OUString name;
635 if (!bRemoved)
637 ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
638 name = StrTitle::getTitle( ucbContent );
641 if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-component"))
643 // xxx todo: probe and evaluate component xml description
645 auto const iter = params.find(OString("platform"));
646 bool bPlatformFits(iter == params.end());
647 OUString aPlatform;
648 if (!bPlatformFits) // platform is specified, we have to check
650 aPlatform = iter->second.m_sValue;
651 bPlatformFits = platform_fits(aPlatform);
653 // If the package is being removed, do not care whether
654 // platform fits. We won't be using it anyway.
655 if (bPlatformFits || bRemoved) {
656 auto const iterType = params.find(OString("type"));
657 if (iterType != params.end())
659 OUString const & value = iterType->second.m_sValue;
660 if (value.equalsIgnoreAsciiCase("native")) {
661 if (bPlatformFits)
662 return new BackendImpl::ComponentPackageImpl(
663 this, url, name, m_xDynComponentTypeInfo,
664 "com.sun.star.loader.SharedLibrary",
665 bRemoved, identifier);
666 else
667 return new BackendImpl::OtherPlatformPackageImpl(
668 this, url, name, m_xDynComponentTypeInfo,
669 bRemoved, identifier, aPlatform);
671 if (value.equalsIgnoreAsciiCase("Java")) {
672 return new BackendImpl::ComponentPackageImpl(
673 this, url, name, m_xJavaComponentTypeInfo,
674 "com.sun.star.loader.Java2",
675 bRemoved, identifier);
677 if (value.equalsIgnoreAsciiCase("Python")) {
678 return new BackendImpl::ComponentPackageImpl(
679 this, url, name, m_xPythonComponentTypeInfo,
680 "com.sun.star.loader.Python",
681 bRemoved, identifier);
686 else if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-components"))
688 auto const iter = params.find(OString("platform"));
689 if (iter == params.end() || platform_fits(iter->second.m_sValue)) {
690 return new BackendImpl::ComponentsPackageImpl(
691 this, url, name, m_xComponentsTypeInfo, bRemoved,
692 identifier);
695 else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-typelibrary"))
697 auto const iter = params.find(OString("type"));
698 if (iter != params.end()) {
699 OUString const & value = iter->second.m_sValue;
700 if (value.equalsIgnoreAsciiCase("RDB"))
702 return new BackendImpl::TypelibraryPackageImpl(
703 this, url, name, m_xRDBTypelibTypeInfo,
704 false /* rdb */, bRemoved, identifier);
706 if (value.equalsIgnoreAsciiCase("Java")) {
707 return new BackendImpl::TypelibraryPackageImpl(
708 this, url, name, m_xJavaTypelibTypeInfo,
709 true /* jar */, bRemoved, identifier);
715 throw lang::IllegalArgumentException(
716 StrUnsupportedMediaType() + mediaType,
717 static_cast<OWeakObject *>(this),
718 static_cast<sal_Int16>(-1) );
722 void BackendImpl::unorc_verify_init(
723 Reference<XCommandEnvironment> const & xCmdEnv )
725 if (transientMode())
726 return;
727 const ::osl::MutexGuard guard( getMutex() );
728 if (! m_unorc_inited)
730 // common rc:
731 ::ucbhelper::Content ucb_content;
732 if (create_ucb_content(
733 &ucb_content,
734 makeURL( getCachePath(), "unorc" ),
735 xCmdEnv, false /* no throw */ ))
737 OUString line;
738 if (readLine( &line, "UNO_JAVA_CLASSPATH=", ucb_content,
739 RTL_TEXTENCODING_UTF8 ))
741 sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1;
742 do {
743 OUString token( line.getToken( 0, ' ', index ).trim() );
744 if (!token.isEmpty())
746 if (create_ucb_content(
747 nullptr, expandUnoRcTerm(token), xCmdEnv,
748 false /* no throw */ ))
750 //The jar file may not exist anymore if a shared or bundled
751 //extension was removed, but it can still be in the unorc
752 //After running XExtensionManager::synchronize, the unorc is
753 //cleaned up
754 m_jar_typelibs.push_back( token );
758 while (index >= 0);
760 if (readLine( &line, "UNO_TYPES=", ucb_content,
761 RTL_TEXTENCODING_UTF8 )) {
762 sal_Int32 index = sizeof ("UNO_TYPES=") - 1;
763 do {
764 OUString token( line.getToken( 0, ' ', index ).trim() );
765 if (!token.isEmpty())
767 if (token[ 0 ] == '?')
768 token = token.copy( 1 );
769 if (create_ucb_content(
770 nullptr, expandUnoRcTerm(token), xCmdEnv,
771 false /* no throw */ ))
773 //The RDB file may not exist anymore if a shared or bundled
774 //extension was removed, but it can still be in the unorc.
775 //After running XExtensionManager::synchronize, the unorc is
776 //cleaned up
777 m_rdb_typelibs.push_back( token );
781 while (index >= 0);
783 if (readLine( &line, "UNO_SERVICES=", ucb_content,
784 RTL_TEXTENCODING_UTF8 ))
786 // The UNO_SERVICES line always has the BNF form
787 // "UNO_SERVICES="
788 // ("?$ORIGIN/" <common-rdb>)? -- first
789 // "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}"? -- second
790 // ("?" ("BUNDLED_EXTENSIONS" | -- third
791 // "UNO_SHARED_PACKAGES_CACHE" | "UNO_USER_PACKAGES_CACHE")
792 // ...)*
793 // so can unambiguously be split into its three parts:
794 int state = 1;
795 for (sal_Int32 i = RTL_CONSTASCII_LENGTH("UNO_SERVICES=");
796 i >= 0;)
798 OUString token(line.getToken(0, ' ', i));
799 if (!token.isEmpty())
801 if (state == 1 && token.match("?$ORIGIN/"))
803 m_commonRDB_orig = token.copy(
804 RTL_CONSTASCII_LENGTH("?$ORIGIN/"));
805 state = 2;
807 else if ( state <= 2 && token == "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" )
809 state = 3;
811 else
813 if (token[0] == '?')
815 token = token.copy(1);
817 m_components.push_back(token);
818 state = 3;
824 // native rc:
825 if (create_ucb_content(
826 &ucb_content,
827 makeURL( getCachePath(), getPlatformString() + "rc"),
828 xCmdEnv, false /* no throw */ )) {
829 if (readLine( &line, "UNO_SERVICES=", ucb_content,
830 RTL_TEXTENCODING_UTF8 )) {
831 m_nativeRDB_orig = line.copy(
832 sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 );
836 m_unorc_modified = false;
837 m_unorc_inited = true;
842 void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv )
844 if (transientMode())
845 return;
846 if (!m_unorc_inited || !m_unorc_modified)
847 return;
849 OStringBuffer buf;
851 buf.append("ORIGIN=");
852 OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
853 OString osOrigin = OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
854 buf.append(osOrigin);
855 buf.append(LF);
857 if (! m_jar_typelibs.empty())
859 auto iPos( m_jar_typelibs.cbegin() );
860 auto const iEnd( m_jar_typelibs.cend() );
861 buf.append( "UNO_JAVA_CLASSPATH=" );
862 while (iPos != iEnd) {
863 // encoded ASCII file-urls:
864 const OString item(
865 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
866 buf.append( item );
867 ++iPos;
868 if (iPos != iEnd)
869 buf.append( ' ' );
871 buf.append(LF);
873 if (! m_rdb_typelibs.empty())
875 auto iPos( m_rdb_typelibs.cbegin() );
876 auto const iEnd( m_rdb_typelibs.cend() );
877 buf.append( "UNO_TYPES=" );
878 while (iPos != iEnd) {
879 buf.append( '?' );
880 // encoded ASCII file-urls:
881 const OString item(
882 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
883 buf.append( item );
884 ++iPos;
885 if (iPos != iEnd)
886 buf.append( ' ' );
888 buf.append(LF);
891 // If we duplicated the common or native rdb then we must use those urls
892 //otherwise we use those of the original files. That is, m_commonRDB_orig
893 //and m_nativeRDB_orig;
894 OUString sCommonRDB(m_commonRDB.isEmpty() ? m_commonRDB_orig : m_commonRDB );
895 OUString sNativeRDB(m_nativeRDB.isEmpty() ? m_nativeRDB_orig : m_nativeRDB );
897 if (!sCommonRDB.isEmpty() || !sNativeRDB.isEmpty() ||
898 !m_components.empty())
900 buf.append( "UNO_SERVICES=" );
901 bool space = false;
902 if (!sCommonRDB.isEmpty())
904 buf.append( "?$ORIGIN/" );
905 buf.append( OUStringToOString(
906 sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
907 space = true;
909 if (!sNativeRDB.isEmpty())
911 if (space)
913 buf.append(' ');
915 buf.append( "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" );
916 space = true;
918 // write native rc:
919 OString buf2 =
920 "ORIGIN=" +
921 osOrigin +
922 OStringChar(LF) +
923 "UNO_SERVICES=?$ORIGIN/" +
924 OUStringToOString( sNativeRDB, RTL_TEXTENCODING_ASCII_US ) +
925 OStringChar(LF);
927 const Reference<io::XInputStream> xData(
928 ::xmlscript::createInputStream(
929 reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
930 buf2.getLength() ) );
931 ::ucbhelper::Content ucb_content(
932 makeURL( getCachePath(), getPlatformString() + "rc" ),
933 xCmdEnv, m_xComponentContext );
934 ucb_content.writeStream( xData, true /* replace existing */ );
936 for (auto const& component : m_components)
938 if (space)
940 buf.append(' ');
942 buf.append('?');
943 buf.append(OUStringToOString(component, RTL_TEXTENCODING_UTF8));
944 space = true;
946 buf.append(LF);
949 // write unorc:
950 const Reference<io::XInputStream> xData(
951 ::xmlscript::createInputStream(
952 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
953 buf.getLength() ) );
954 ::ucbhelper::Content ucb_content(
955 makeURL( getCachePath(), "unorc" ), xCmdEnv, m_xComponentContext );
956 ucb_content.writeStream( xData, true /* replace existing */ );
958 m_unorc_modified = false;
962 void BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
963 Reference<XCommandEnvironment> const & xCmdEnv )
965 const OUString rcterm( dp_misc::makeRcTerm(url_) );
966 const ::osl::MutexGuard guard( getMutex() );
967 unorc_verify_init( xCmdEnv );
968 std::deque<OUString> & rSet = getRcItemList(kind);
969 if (std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
970 rSet.push_front( rcterm ); // prepend to list, thus overriding
971 // write immediately:
972 m_unorc_modified = true;
973 unorc_flush( xCmdEnv );
978 void BackendImpl::removeFromUnoRc(
979 RcItem kind, OUString const & url_,
980 Reference<XCommandEnvironment> const & xCmdEnv )
982 const OUString rcterm( dp_misc::makeRcTerm(url_) );
983 const ::osl::MutexGuard guard( getMutex() );
984 unorc_verify_init( xCmdEnv );
985 std::deque<OUString> & aRcItemList = getRcItemList(kind);
986 aRcItemList.erase(std::remove(aRcItemList.begin(), aRcItemList.end(), rcterm), aRcItemList.end());
987 // write immediately:
988 m_unorc_modified = true;
989 unorc_flush( xCmdEnv );
993 bool BackendImpl::hasInUnoRc(
994 RcItem kind, OUString const & url_ )
996 const OUString rcterm( dp_misc::makeRcTerm(url_) );
997 const ::osl::MutexGuard guard( getMutex() );
998 std::deque<OUString> const & rSet = getRcItemList(kind);
999 return std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1002 css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext()
1003 const
1005 css::uno::Reference< css::uno::XComponentContext > rootContext(
1006 getComponentContext()->getValueByName("_root"),
1007 css::uno::UNO_QUERY);
1008 return rootContext.is() ? rootContext : getComponentContext();
1012 void BackendImpl::releaseObject( OUString const & id )
1014 const ::osl::MutexGuard guard( getMutex() );
1015 m_backendObjects.erase( id );
1019 Reference<XInterface> BackendImpl::getObject( OUString const & id )
1021 const ::osl::MutexGuard guard( getMutex() );
1022 const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1023 if (iFind == m_backendObjects.end())
1024 return Reference<XInterface>();
1025 else
1026 return iFind->second;
1030 Reference<XInterface> BackendImpl::insertObject(
1031 OUString const & id, Reference<XInterface> const & xObject )
1033 const ::osl::MutexGuard guard( getMutex() );
1034 const std::pair<t_string2object::iterator, bool> insertion(
1035 m_backendObjects.emplace( id, xObject ) );
1036 return insertion.first->second;
1040 Reference<XComponentContext> raise_uno_process(
1041 Reference<XComponentContext> const & xContext,
1042 ::rtl::Reference<AbortChannel> const & abortChannel )
1044 OSL_ASSERT( xContext.is() );
1046 OUString url( util::theMacroExpander::get(xContext)->expandMacros( "$URE_BIN_DIR/uno" ) );
1048 const OUString connectStr = "uno:pipe,name=" + generateRandomPipeId() + ";urp;uno.ComponentContext";
1050 // raise core UNO process to register/run a component,
1051 // javavm service uses unorc next to executable to retrieve deployed
1052 // jar typelibs
1054 std::vector<OUString> args{
1055 #if OSL_DEBUG_LEVEL == 0
1056 "--quiet",
1057 #endif
1058 "--singleaccept",
1059 "-u",
1060 connectStr,
1061 // don't inherit from unorc:
1062 "-env:INIFILENAME=" };
1064 //now add the bootstrap variables which were supplied on the command line
1065 std::vector<OUString> bootvars = getCmdBootstrapVariables();
1066 args.insert(args.end(), bootvars.begin(), bootvars.end());
1068 oslProcess hProcess;
1069 try {
1070 hProcess = raiseProcess(
1071 url, comphelper::containerToSequence(args) );
1073 catch (...) {
1074 OUStringBuffer sMsg = "error starting process: " + url;
1075 for(const auto& arg : args)
1076 sMsg.append(" ").append(arg);
1077 throw uno::RuntimeException(sMsg.makeStringAndClear());
1079 try {
1080 return Reference<XComponentContext>(
1081 resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1082 UNO_QUERY_THROW );
1084 catch (...) {
1085 // try to terminate process:
1086 if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1088 OSL_ASSERT( false );
1090 throw;
1094 void extractComponentData(
1095 css::uno::Reference< css::uno::XComponentContext > const & context,
1096 css::uno::Reference< css::registry::XRegistryKey > const & registry,
1097 ComponentBackendDb::Data * data,
1098 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1099 css::uno::Reference< css::loader::XImplementationLoader > const &
1100 componentLoader,
1101 OUString const & componentUrl)
1103 OSL_ASSERT(
1104 context.is() && registry.is() && data != nullptr && componentLoader.is());
1105 OUString registryName(registry->getKeyName());
1106 sal_Int32 prefix = registryName.getLength();
1107 if (!registryName.endsWith("/")) {
1108 prefix += RTL_CONSTASCII_LENGTH("/");
1110 css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1111 keys(registry->openKeys());
1112 css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1113 context->getServiceManager(), css::uno::UNO_SET_THROW);
1114 for (sal_Int32 i = 0; i < keys.getLength(); ++i) {
1115 OUString name(keys[i]->getKeyName().copy(prefix));
1116 data->implementationNames.push_back(name);
1117 css::uno::Reference< css::registry::XRegistryKey > singletons(
1118 keys[i]->openKey("UNO/SINGLETONS"));
1119 if (singletons.is()) {
1120 sal_Int32 prefix2 = keys[i]->getKeyName().getLength() +
1121 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1122 css::uno::Sequence<
1123 css::uno::Reference< css::registry::XRegistryKey > >
1124 singletonKeys(singletons->openKeys());
1125 for (sal_Int32 j = 0; j < singletonKeys.getLength(); ++j) {
1126 data->singletons.emplace_back(
1127 singletonKeys[j]->getKeyName().copy(prefix2), name);
1130 if (factories != nullptr) {
1131 factories->push_back(
1132 componentLoader->activate(
1133 name, OUString(), componentUrl, keys[i]));
1138 void BackendImpl::ComponentPackageImpl::getComponentInfo(
1139 ComponentBackendDb::Data * data,
1140 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1141 Reference<XComponentContext> const & xContext )
1143 const Reference<loader::XImplementationLoader> xLoader(
1144 xContext->getServiceManager()->createInstanceWithContext(
1145 m_loader, xContext ), UNO_QUERY );
1146 if (! xLoader.is())
1148 throw css::deployment::DeploymentException(
1149 "cannot instantiate loader " + m_loader,
1150 static_cast< OWeakObject * >(this), Any());
1153 // HACK: highly dependent on stoc/source/servicemanager
1154 // and stoc/source/implreg implementation which rely on the same
1155 // services.rdb format!
1156 // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1157 // writeRegistryInfo, however, but are known, fixed values here, so
1158 // can be passed into extractComponentData
1159 OUString url(getURL());
1160 const Reference<registry::XSimpleRegistry> xMemReg(
1161 xContext->getServiceManager()->createInstanceWithContext(
1162 "com.sun.star.registry.SimpleRegistry", xContext ),
1163 UNO_QUERY_THROW );
1164 xMemReg->open( OUString() /* in mem */, false, true );
1165 xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1166 extractComponentData(
1167 xContext, xMemReg->getRootKey(), data, factories, xLoader, url);
1170 void BackendImpl::ComponentPackageImpl::componentLiveInsertion(
1171 ComponentBackendDb::Data const & data,
1172 std::vector< css::uno::Reference< css::uno::XInterface > > const &
1173 factories)
1175 css::uno::Reference< css::uno::XComponentContext > rootContext(
1176 getMyBackend()->getRootContext());
1177 css::uno::Reference< css::container::XSet > set(
1178 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1179 std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1180 factory(factories.begin());
1181 for (auto const& implementationName : data.implementationNames)
1183 try {
1184 set->insert(css::uno::Any(*factory++));
1185 } catch (const container::ElementExistException &) {
1186 SAL_WARN("desktop.deployment", "implementation already registered " << implementationName);
1189 if (!data.singletons.empty()) {
1190 css::uno::Reference< css::container::XNameContainer > cont(
1191 rootContext, css::uno::UNO_QUERY_THROW);
1192 for (auto const& singleton : data.singletons)
1194 OUString name("/singletons/" + singleton.first);
1195 //TODO: Update should be atomic:
1196 try {
1197 cont->removeByName( name + "/arguments");
1198 } catch (const container::NoSuchElementException &) {}
1199 try {
1200 cont->insertByName( name + "/service", css::uno::Any(singleton.second));
1201 } catch (const container::ElementExistException &) {
1202 cont->replaceByName( name + "/service", css::uno::Any(singleton.second));
1204 try {
1205 cont->insertByName(name, css::uno::Any());
1206 } catch (const container::ElementExistException &) {
1207 SAL_WARN("desktop.deployment", "singleton already registered " << singleton.first);
1208 cont->replaceByName(name, css::uno::Any());
1214 void BackendImpl::ComponentPackageImpl::componentLiveRemoval(
1215 ComponentBackendDb::Data const & data)
1217 css::uno::Reference< css::uno::XComponentContext > rootContext(
1218 getMyBackend()->getRootContext());
1219 css::uno::Reference< css::container::XSet > set(
1220 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1221 for (auto const& implementationName : data.implementationNames)
1223 try {
1224 set->remove(css::uno::Any(implementationName));
1225 } catch (const css::container::NoSuchElementException &) {
1226 // ignore if factory has not been live deployed
1229 if (!data.singletons.empty()) {
1230 css::uno::Reference< css::container::XNameContainer > cont(
1231 rootContext, css::uno::UNO_QUERY_THROW);
1232 for (auto const& singleton : data.singletons)
1234 OUString name("/singletons/" + singleton.first);
1235 //TODO: Removal should be atomic:
1236 try {
1237 cont->removeByName(name);
1238 } catch (const container::NoSuchElementException &) {}
1239 try {
1240 cont->removeByName( name + "/service" );
1241 } catch (const container::NoSuchElementException &) {}
1242 try {
1243 cont->removeByName( name + "/arguments" );
1244 } catch (const container::NoSuchElementException &) {}
1249 // Package
1251 //We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1252 //And it also shows the problem if another extension has overwritten an implementation
1253 //entry, because it contains the same service implementation
1254 beans::Optional< beans::Ambiguous<sal_Bool> >
1255 BackendImpl::ComponentPackageImpl::isRegistered_(
1256 ::osl::ResettableMutexGuard &,
1257 ::rtl::Reference<AbortChannel> const & abortChannel,
1258 Reference<XCommandEnvironment> const & )
1260 if (m_registered == REG_UNINIT)
1262 m_registered = REG_NOT_REGISTERED;
1263 const Reference<registry::XSimpleRegistry> xRDB( getRDB() );
1264 if (xRDB.is())
1266 bool bAmbiguousComponentName = false;
1267 // lookup rdb for location URL:
1268 const Reference<registry::XRegistryKey> xRootKey(
1269 xRDB->getRootKey() );
1270 const Reference<registry::XRegistryKey> xImplKey(
1271 xRootKey->openKey( "IMPLEMENTATIONS" ) );
1272 Sequence<OUString> implNames;
1273 if (xImplKey.is() && xImplKey->isValid())
1274 implNames = xImplKey->getKeyNames();
1275 OUString const * pImplNames = implNames.getConstArray();
1276 sal_Int32 pos = implNames.getLength();
1277 for ( ; pos--; )
1279 checkAborted( abortChannel );
1280 const OUString key(
1281 pImplNames[ pos ] + "/UNO/LOCATION" );
1282 const Reference<registry::XRegistryKey> xKey(
1283 xRootKey->openKey(key) );
1284 if (xKey.is() && xKey->isValid())
1286 const OUString location( xKey->getAsciiValue() );
1287 if (location.equalsIgnoreAsciiCase( getURL() ))
1289 break;
1291 else
1293 //try to match only the file name
1294 OUString thisUrl(getURL());
1295 OUString thisFileName(thisUrl.copy(thisUrl.lastIndexOf('/')));
1297 OUString locationFileName(location.copy(location.lastIndexOf('/')));
1298 if (locationFileName.equalsIgnoreAsciiCase(thisFileName))
1299 bAmbiguousComponentName = true;
1303 if (pos >= 0)
1304 m_registered = REG_REGISTERED;
1305 else if (bAmbiguousComponentName)
1306 m_registered = REG_MAYBE_REGISTERED;
1310 //Different extensions can use the same service implementations. Then the extensions
1311 //which was installed last will overwrite the one from the other extension. That is
1312 //the registry will contain the path (the location) of the library or jar of the
1313 //second extension. In this case isRegistered called for the lib of the first extension
1314 //would return "not registered". That would mean that during uninstallation
1315 //XPackage::registerPackage is not called, because it just was not registered. This is,
1316 //however, necessary for jar files. Registering and unregistering update
1317 //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1318 //Therefore, we will return always "is ambiguous" if the path of this component cannot
1319 //be found in the registry and if there is another path and both have the same file name (but
1320 //the rest of the path is different).
1321 //If the caller cannot precisely determine that this package was registered, then it must
1322 //call registerPackage.
1323 bool bAmbiguous = m_registered == REG_VOID // REG_VOID == we are in the progress of unregistration
1324 || m_registered == REG_MAYBE_REGISTERED;
1325 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1326 true /* IsPresent */,
1327 beans::Ambiguous<sal_Bool>(
1328 m_registered == REG_REGISTERED, bAmbiguous) );
1332 void BackendImpl::ComponentPackageImpl::processPackage_(
1333 ::osl::ResettableMutexGuard &,
1334 bool doRegisterPackage,
1335 bool startup,
1336 ::rtl::Reference<AbortChannel> const & abortChannel,
1337 Reference<XCommandEnvironment> const & xCmdEnv )
1339 BackendImpl * that = getMyBackend();
1340 OUString url(getURL());
1341 if (doRegisterPackage) {
1342 ComponentBackendDb::Data data;
1343 css::uno::Reference< css::uno::XComponentContext > context;
1344 if (startup) {
1345 context = that->getComponentContext();
1346 } else {
1347 context.set(that->getObject(url), css::uno::UNO_QUERY);
1348 if (!context.is()) {
1349 context.set(
1350 that->insertObject(
1351 url,
1352 raise_uno_process(
1353 that->getComponentContext(), abortChannel)),
1354 css::uno::UNO_QUERY_THROW);
1357 css::uno::Reference< css::registry::XImplementationRegistration> impreg(
1358 context->getServiceManager()->createInstanceWithContext(
1359 "com.sun.star.registry.ImplementationRegistration",
1360 context),
1361 css::uno::UNO_QUERY_THROW);
1362 css::uno::Reference< css::registry::XSimpleRegistry > rdb(getRDB());
1363 impreg->registerImplementation(m_loader, url, rdb);
1364 // Only write to unorc after successful registration; it may fail if
1365 // there is no suitable java
1366 if (m_loader == "com.sun.star.loader.Java2" && !jarManifestHeaderPresent(url, "UNO-Type-Path", xCmdEnv))
1368 that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1369 data.javaTypeLibrary = true;
1371 std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1372 getComponentInfo(&data, startup ? nullptr : &factories, context);
1373 if (!startup) {
1374 try {
1375 componentLiveInsertion(data, factories);
1376 } catch (css::uno::Exception &) {
1377 TOOLS_INFO_EXCEPTION("desktop.deployment", "caught");
1378 try {
1379 impreg->revokeImplementation(url, rdb);
1380 } catch (css::uno::RuntimeException &) {
1381 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignored");
1383 throw;
1386 m_registered = REG_REGISTERED;
1387 that->addDataToDb(url, data);
1388 } else { // revoke
1389 m_registered = REG_VOID;
1390 ComponentBackendDb::Data data(that->readDataFromDb(url));
1391 css::uno::Reference< css::uno::XComponentContext > context(
1392 that->getObject(url), css::uno::UNO_QUERY);
1393 bool remoteContext = context.is();
1394 if (!remoteContext) {
1395 context = that->getComponentContext();
1397 if (!startup) {
1398 componentLiveRemoval(data);
1400 css::uno::Reference< css::registry::XImplementationRegistration >(
1401 context->getServiceManager()->createInstanceWithContext(
1402 "com.sun.star.registry.ImplementationRegistration",
1403 context),
1404 css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1405 if (data.javaTypeLibrary) {
1406 that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1408 if (remoteContext) {
1409 that->releaseObject(url);
1411 m_registered = REG_NOT_REGISTERED;
1412 getMyBackend()->revokeEntryFromDb(url);
1416 BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1417 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1418 OUString const & url, OUString const & name,
1419 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1420 bool jarFile, bool bRemoved, OUString const & identifier)
1421 : Package( myBackend, url, name, name /* display-name */,
1422 xPackageType, bRemoved, identifier),
1423 m_jarFile( jarFile )
1427 // Package
1428 BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1430 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1431 if (nullptr == pBackend)
1433 //May throw a DisposedException
1434 check();
1435 //We should never get here...
1436 throw RuntimeException( "Failed to get the BackendImpl",
1437 static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1439 return pBackend;
1442 beans::Optional< beans::Ambiguous<sal_Bool> >
1443 BackendImpl::TypelibraryPackageImpl::isRegistered_(
1444 ::osl::ResettableMutexGuard &,
1445 ::rtl::Reference<AbortChannel> const &,
1446 Reference<XCommandEnvironment> const & )
1448 BackendImpl * that = getMyBackend();
1449 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1450 true /* IsPresent */,
1451 beans::Ambiguous<sal_Bool>(
1452 that->hasInUnoRc(
1453 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1454 false /* IsAmbiguous */ ) );
1458 void BackendImpl::TypelibraryPackageImpl::processPackage_(
1459 ::osl::ResettableMutexGuard &,
1460 bool doRegisterPackage,
1461 bool /*startup*/,
1462 ::rtl::Reference<AbortChannel> const &,
1463 Reference<XCommandEnvironment> const & xCmdEnv )
1465 BackendImpl * that = getMyBackend();
1466 const OUString url( getURL() );
1468 if (doRegisterPackage)
1470 // live insertion:
1471 if (m_jarFile) {
1472 // xxx todo add to classpath at runtime: ???
1473 //SB: It is probably not worth it to add the live inserted type
1474 // library JAR to the UnoClassLoader in the soffice process. Any
1475 // live inserted component JAR that might reference this type
1476 // library JAR runs in its own uno process, so there is probably no
1477 // Java code in the soffice process that would see any UNO types
1478 // introduced by this type library JAR.
1480 else // RDB:
1482 css::uno::Reference< css::container::XSet >(
1483 that->getComponentContext()->getValueByName(
1484 "/singletons"
1485 "/com.sun.star.reflection.theTypeDescriptionManager"),
1486 css::uno::UNO_QUERY_THROW)->insert(
1487 css::uno::makeAny(expandUnoRcUrl(url)));
1490 that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1491 url, xCmdEnv );
1493 else // revokePackage()
1495 that->removeFromUnoRc(
1496 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1498 // revoking types at runtime, possible, sensible?
1499 if (!m_jarFile) {
1500 css::uno::Reference< css::container::XSet >(
1501 that->getComponentContext()->getValueByName(
1502 "/singletons"
1503 "/com.sun.star.reflection.theTypeDescriptionManager"),
1504 css::uno::UNO_QUERY_THROW)->remove(
1505 css::uno::makeAny(expandUnoRcUrl(url)));
1510 BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl(
1511 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1512 OUString const & url, OUString const & name,
1513 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1514 bool bRemoved, OUString const & identifier, OUString const& rPlatform)
1515 : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier)
1516 , m_aPlatform(rPlatform)
1518 OSL_PRECOND(bRemoved, "this class can only be used for removing packages!");
1521 BackendImpl *
1522 BackendImpl::OtherPlatformPackageImpl::getMyBackend() const
1524 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1525 if (nullptr == pBackend)
1527 //Throws a DisposedException
1528 check();
1529 //We should never get here...
1530 throw RuntimeException("Failed to get the BackendImpl",
1531 static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this)));
1533 return pBackend;
1536 Reference<registry::XSimpleRegistry>
1537 BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const
1539 OUString const aRDB(m_aPlatform + ".rdb");
1540 OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB));
1542 Reference<registry::XSimpleRegistry> xRegistry;
1546 xRegistry.set(
1547 impl_createInstance("com.sun.star.registry.SimpleRegistry"),
1548 UNO_QUERY)
1550 if (xRegistry.is())
1551 xRegistry->open(expandUnoRcUrl(aRDBPath), false, false);
1553 catch (registry::InvalidRegistryException const&)
1555 // If the registry does not exist, we do not need to bother at all
1556 xRegistry.set(nullptr);
1559 SAL_WARN_IF( !xRegistry.is(), "desktop.deployment", "could not create registry for the package's platform");
1560 return xRegistry;
1563 Reference<XInterface>
1564 BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService)
1565 const
1567 Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext());
1568 OSL_ASSERT(xContext.is());
1569 Reference<XInterface> xService;
1570 if (xContext.is())
1571 xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext));
1572 return xService;
1575 beans::Optional<beans::Ambiguous<sal_Bool> >
1576 BackendImpl::OtherPlatformPackageImpl::isRegistered_(
1577 ::osl::ResettableMutexGuard& /* guard */,
1578 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1579 Reference<XCommandEnvironment> const& /* xCmdEnv */ )
1581 return beans::Optional<beans::Ambiguous<sal_Bool> >(true,
1582 beans::Ambiguous<sal_Bool>(true, false));
1585 void
1586 BackendImpl::OtherPlatformPackageImpl::processPackage_(
1587 ::osl::ResettableMutexGuard& /* guard */,
1588 bool bRegisterPackage,
1589 bool /* bStartup */,
1590 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1591 Reference<XCommandEnvironment> const& /* xCmdEnv */)
1593 OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!");
1595 OUString const aURL(getURL());
1597 Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB());
1598 Reference<registry::XImplementationRegistration> const xImplReg(
1599 impl_createInstance("com.sun.star.registry.ImplementationRegistration"),
1600 UNO_QUERY)
1602 if (xImplReg.is() && xServicesRDB.is())
1603 xImplReg->revokeImplementation(aURL, xServicesRDB);
1604 if (xServicesRDB.is())
1605 xServicesRDB->close();
1607 getMyBackend()->revokeEntryFromDb(aURL);
1610 BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1612 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1613 if (nullptr == pBackend)
1615 //Throws a DisposedException
1616 check();
1617 //We should never get here...
1618 throw RuntimeException("Failed to get the BackendImpl",
1619 static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1621 return pBackend;
1624 beans::Optional< beans::Ambiguous<sal_Bool> >
1625 BackendImpl::ComponentsPackageImpl::isRegistered_(
1626 ::osl::ResettableMutexGuard &,
1627 ::rtl::Reference<AbortChannel> const &,
1628 Reference<XCommandEnvironment> const & )
1630 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1631 true,
1632 beans::Ambiguous<sal_Bool>(
1633 getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1636 void BackendImpl::ComponentsPackageImpl::processPackage_(
1637 ::osl::ResettableMutexGuard &,
1638 bool doRegisterPackage,
1639 bool startup,
1640 ::rtl::Reference<AbortChannel> const & abortChannel,
1641 Reference<XCommandEnvironment> const & xCmdEnv )
1643 BackendImpl * that = getMyBackend();
1644 OUString url(getURL());
1645 if (doRegisterPackage) {
1646 if (!startup) {
1647 css::uno::Reference< css::uno::XComponentContext > context(
1648 that->getObject(url), css::uno::UNO_QUERY);
1649 if (!context.is()) {
1650 context.set(
1651 that->insertObject(
1652 url,
1653 raise_uno_process(
1654 that->getComponentContext(), abortChannel)),
1655 css::uno::UNO_QUERY_THROW);
1657 // This relies on the root component context's service manager
1658 // supporting the extended XSet semantics:
1659 css::uno::Sequence< css::beans::NamedValue > args
1661 { "uri", css::uno::makeAny(expandUnoRcUrl(url)) },
1662 { "component-context", css::uno::makeAny(context) }
1664 css::uno::Reference< css::container::XSet > smgr(
1665 that->getRootContext()->getServiceManager(),
1666 css::uno::UNO_QUERY_THROW);
1667 smgr->insert(css::uno::makeAny(args));
1669 that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1670 } else { // revoke
1671 that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1672 if (!startup) {
1673 // This relies on the root component context's service manager
1674 // supporting the extended XSet semantics:
1675 css::uno::Sequence< css::beans::NamedValue > args { { "uri", css::uno::makeAny(expandUnoRcUrl(url)) } };
1676 css::uno::Reference< css::container::XSet > smgr(
1677 that->getRootContext()->getServiceManager(),
1678 css::uno::UNO_QUERY_THROW);
1679 smgr->remove(css::uno::makeAny(args));
1681 that->releaseObject(url);
1682 that->revokeEntryFromDb(url); // in case it got added with old code
1686 BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1687 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
1688 OUString const & url, OUString const & name,
1689 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1690 bool bRemoved, OUString const & identifier)
1691 : Package( myBackend, url, name, name /* display-name */,
1692 xPackageType, bRemoved, identifier)
1695 } // anon namespace
1697 namespace sdecl = comphelper::service_decl;
1698 sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
1699 sdecl::ServiceDecl const serviceDecl(
1700 serviceBI,
1701 IMPLEMENTATION_NAME,
1702 BACKEND_SERVICE_NAME );
1704 } // namespace component
1705 } // namespace backend
1706 } // namespace dp_registry
1709 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */