LibreOffice Module desktop (master) 1
dp_component.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
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>
34#include <ucbhelper/content.hxx>
36#include <utility>
38#include <svl/inettype.hxx>
39#include <tools/diagnose_ex.h>
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"
59
60using namespace ::dp_misc;
61using namespace ::com::sun::star;
62using namespace ::com::sun::star::uno;
63using namespace ::com::sun::star::ucb;
64
66namespace {
67
71std::vector<OUString> getCmdBootstrapVariables()
72{
73 std::vector<OUString> ret;
74 sal_uInt32 count = osl_getCommandArgCount();
75 for (sal_uInt32 i = 0; i < count; i++)
76 {
77 OUString arg;
78 osl_getCommandArg(i, &arg.pData);
79 if (arg.startsWith("-env:"))
80 ret.push_back(arg);
81 }
82 return ret;
83}
84
85bool jarManifestHeaderPresent(
86 OUString const & url, OUString const & name,
87 Reference<XCommandEnvironment> const & xCmdEnv )
88{
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
98 &manifestContent, buf, xCmdEnv,
99 false /* no throw */ )
100 && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US );
101}
102
103
104class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
105{
106 class ComponentPackageImpl : public ::dp_registry::backend::Package
107 {
108 BackendImpl * getMyBackend() const;
109
110 const OUString m_loader;
111
112 enum class Reg { Uninit, Void, Registered, NotRegistered, MaybeRegistered };
114
115 void getComponentInfo(
116 ComponentBackendDb::Data * data,
117 std::vector< css::uno::Reference< css::uno::XInterface > > *
118 factories,
119 Reference<XComponentContext> const & xContext );
120
121 void componentLiveInsertion(
122 ComponentBackendDb::Data const & data,
123 std::vector< css::uno::Reference< css::uno::XInterface > > const &
124 factories);
125
126 void componentLiveRemoval(ComponentBackendDb::Data const & data);
127
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;
139
140 Reference<registry::XSimpleRegistry> getRDB() const;
141
142 public:
143 ComponentPackageImpl(
145 OUString const & url, OUString const & name,
146 Reference<deployment::XPackageTypeInfo> const & xPackageType,
147 OUString loader, bool bRemoved,
148 OUString const & identifier);
149 };
150 friend class ComponentPackageImpl;
151
152 class ComponentsPackageImpl : public ::dp_registry::backend::Package
153 {
154 BackendImpl * getMyBackend() const;
155
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(
170 OUString const & url, OUString const & name,
171 Reference<deployment::XPackageTypeInfo> const & xPackageType,
172 bool bRemoved, OUString const & identifier);
173 };
174 friend class ComponentsPackageImpl;
175
176 class TypelibraryPackageImpl : public ::dp_registry::backend::Package
177 {
178 BackendImpl * getMyBackend() const;
179
180 const bool m_jarFile;
181
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;
193
194 public:
195 TypelibraryPackageImpl(
197 OUString const & url, OUString const & name,
198 Reference<deployment::XPackageTypeInfo> const & xPackageType,
199 bool jarFile, bool bRemoved,
200 OUString const & identifier);
201 };
202 friend class TypelibraryPackageImpl;
203
208 class OtherPlatformPackageImpl : public ::dp_registry::backend::Package
209 {
210 public:
211 OtherPlatformPackageImpl(
213 OUString const & url, OUString const & name,
214 Reference<deployment::XPackageTypeInfo> const & xPackageType,
215 bool bRemoved, OUString const & identifier, OUString platform);
216
217 private:
218 BackendImpl * getMyBackend() const;
219
220 Reference<registry::XSimpleRegistry> impl_openRDB() const;
221 Reference<XInterface> impl_createInstance(OUString const& rService) const;
222
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;
234
235 private:
236 OUString const m_aPlatform;
237 };
238 friend class OtherPlatformPackageImpl;
239
240 std::deque<OUString> m_jar_typelibs;
241 std::deque<OUString> m_rdb_typelibs;
242 std::deque<OUString> m_components;
243
244 enum RcItem { RCITEM_JAR_TYPELIB, RCITEM_RDB_TYPELIB, RCITEM_COMPONENTS };
245
246 std::deque<OUString> & getRcItemList( RcItem kind ) {
247 switch (kind)
248 {
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;
255 }
256 }
257
261
262 typedef std::unordered_map< OUString, Reference<XInterface> > t_string2object;
263 t_string2object m_backendObjects;
264
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;
270
271 virtual void SAL_CALL disposing() override;
272
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;
280
281 OUString m_commonRDB;
282 OUString m_nativeRDB;
283
284 //URLs of the original rdbs (before any switching):
287
288 std::unique_ptr<ComponentBackendDb> m_backendDb;
289
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);
293
294 Reference<registry::XSimpleRegistry> m_xCommonRDB;
295 Reference<registry::XSimpleRegistry> m_xNativeRDB;
296
297 void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv );
298 void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv );
299
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 );
304
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 );
310
311 css::uno::Reference< css::uno::XComponentContext > getRootContext() const;
312
313public:
314 BackendImpl( Sequence<Any> const & args,
315 Reference<XComponentContext> const & xComponentContext );
316
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;
321
322 // XPackageRegistry
323 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
324 getSupportedPackageTypes() override;
325
326 virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
327
329
330 //Will be called from ComponentPackageImpl
331 void initServiceRdbFiles();
332};
333
334
335BackendImpl::ComponentPackageImpl::ComponentPackageImpl(
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 )
345{}
346
347Reference<registry::XSimpleRegistry>
348BackendImpl::ComponentPackageImpl::getRDB() const
349{
350 BackendImpl * that = getMyBackend();
351
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
357 {
358 const ::osl::MutexGuard guard( m_aMutex );
359 if (!that->bSwitchedRdbFiles)
360 {
361 that->bSwitchedRdbFiles = true;
362 that->initServiceRdbFiles();
363 }
364 }
365 if ( m_loader == "com.sun.star.loader.SharedLibrary" )
366 return that->m_xNativeRDB;
367 else
368 return that->m_xCommonRDB;
369}
370
371BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const
372{
373 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
374 if (nullptr == pBackend)
375 {
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)));
382 }
383 return pBackend;
384}
385
386
387void BackendImpl::disposing()
388{
389 try {
390 m_backendObjects = t_string2object();
391 if (m_xNativeRDB.is()) {
392 m_xNativeRDB->close();
393 m_xNativeRDB.clear();
394 }
395 if (m_xCommonRDB.is()) {
396 m_xCommonRDB->close();
397 m_xCommonRDB.clear();
398 }
399 unorc_flush( Reference<XCommandEnvironment>() );
400
401 PackageRegistryBackend::disposing();
402 }
403 catch (const RuntimeException &) {
404 throw;
405 }
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 );
411 }
412}
413
414
415void BackendImpl::initServiceRdbFiles()
416{
417 const Reference<XCommandEnvironment> xCmdEnv;
418
419 ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv, m_xComponentContext );
421 // switch common rdb:
422 if (!m_commonRDB_orig.isEmpty())
423 {
424 (void)create_ucb_content(
425 &oldRDB, makeURL( getCachePath(), m_commonRDB_orig),
426 xCmdEnv, false /* no throw */ );
427 }
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())
430 {
431 cacheDir.transferContent(
433 m_commonRDB, NameClash::OVERWRITE );
434 oldRDB = ::ucbhelper::Content();
435 }
436 // switch native rdb:
437 if (!m_nativeRDB_orig.isEmpty())
438 {
439 (void)create_ucb_content(
440 &oldRDB, makeURL(getCachePath(), m_nativeRDB_orig),
441 xCmdEnv, false /* no throw */ );
442 }
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())
447 {
448 cacheDir.transferContent(
450 m_nativeRDB, NameClash::OVERWRITE );
451 }
452
453 // UNO is bootstrapped, flush for next process start:
454 m_unorc_modified = true;
455 unorc_flush( Reference<XCommandEnvironment>() );
456
457
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);
468 }
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);
478 }
479}
480
481BackendImpl::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=" +
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 ) ),
522{
523 const Reference<XCommandEnvironment> xCmdEnv;
524
525 if (transientMode())
526 {
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 */ );
541 }
542 else
543 {
544 unorc_verify_init( xCmdEnv );
545 OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
546 m_backendDb.reset(
547 new ComponentBackendDb(getComponentContext(), dbFile));
548 }
549}
550
551// XServiceInfo
552OUString BackendImpl::getImplementationName()
553{
554 return "com.sun.star.comp.deployment.component.PackageRegistryBackend";
555}
556
557sal_Bool BackendImpl::supportsService( const OUString& ServiceName )
558{
559 return cppu::supportsService(this, ServiceName);
560}
561
562css::uno::Sequence< OUString > BackendImpl::getSupportedServiceNames()
563{
564 return { BACKEND_SERVICE_NAME };
565}
566
567void BackendImpl::addDataToDb(
568 OUString const & url, ComponentBackendDb::Data const & data)
569{
570 if (m_backendDb)
571 m_backendDb->addEntry(url, data);
572}
573
574ComponentBackendDb::Data BackendImpl::readDataFromDb(std::u16string_view url)
575{
576 ComponentBackendDb::Data data;
577 if (m_backendDb)
578 data = m_backendDb->getEntry(url);
579 return data;
580}
581
582void BackendImpl::revokeEntryFromDb(std::u16string_view url)
583{
584 if (m_backendDb)
585 m_backendDb->revokeEntry(url);
586}
587
588// XPackageRegistry
589
590Sequence< Reference<deployment::XPackageTypeInfo> >
591BackendImpl::getSupportedPackageTypes()
592{
593 return m_typeInfos;
594}
595
596void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
597{
598 if (m_backendDb)
599 m_backendDb->removeEntry(url);
600}
601
602// PackageRegistryBackend
603
604Reference<deployment::XPackage> BackendImpl::bindPackage_(
605 OUString const & url, OUString const & mediaType_,
606 bool bRemoved, OUString const & identifier,
607 Reference<XCommandEnvironment> const & xCmdEnv )
608{
609 OUString mediaType(mediaType_);
610 if ( mediaType.isEmpty() || mediaType == "application/vnd.sun.star.uno-component" || mediaType == "application/vnd.sun.star.uno-typelibrary" )
611 {
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))
617 {
618 mediaType = "application/vnd.sun.star.uno-component;type=native;platform=" +
620 }
621 else if (title.endsWithIgnoreAsciiCase(".jar"))
622 {
623 if (jarManifestHeaderPresent(
624 url, "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";
628 }
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";
633 }
634 if (mediaType.isEmpty())
635 throw lang::IllegalArgumentException(
636 StrCannotDetectMediaType() + url,
637 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
638 }
639
640 OUString type, subType;
642 if (INetContentTypes::parse( mediaType, type, subType, &params ))
643 {
644 if (type.equalsIgnoreAsciiCase("application"))
645 {
646 OUString name;
647 if (!bRemoved)
648 {
649 ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
650 name = StrTitle::getTitle( ucbContent );
651 }
652
653 if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-component"))
654 {
655 // xxx todo: probe and evaluate component xml description
656
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
661 {
662 aPlatform = iter->second.m_sValue;
663 bPlatformFits = platform_fits(aPlatform);
664 }
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())
670 {
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);
682 }
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);
688 }
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);
694 }
695 }
696 }
697 }
698 else if (subType.equalsIgnoreAsciiCase("vnd.sun.star.uno-components"))
699 {
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);
705 }
706 }
707 else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-typelibrary"))
708 {
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"))
713 {
714 return new BackendImpl::TypelibraryPackageImpl(
715 this, url, name, m_xRDBTypelibTypeInfo,
716 false /* rdb */, bRemoved, identifier);
717 }
718 if (value.equalsIgnoreAsciiCase("Java")) {
719 return new BackendImpl::TypelibraryPackageImpl(
720 this, url, name, m_xJavaTypelibTypeInfo,
721 true /* jar */, bRemoved, identifier);
722 }
723 }
724 }
725 }
726 }
727 throw lang::IllegalArgumentException(
728 StrUnsupportedMediaType() + mediaType,
729 static_cast<OWeakObject *>(this),
730 static_cast<sal_Int16>(-1) );
731}
732
733
734void BackendImpl::unorc_verify_init(
735 Reference<XCommandEnvironment> const & xCmdEnv )
736{
737 if (transientMode())
738 return;
739 const ::osl::MutexGuard guard( m_aMutex );
740 if ( m_unorc_inited)
741 return;
742
743 // common rc:
744 ::ucbhelper::Content ucb_content;
746 &ucb_content,
747 makeURL( getCachePath(), "unorc" ),
748 xCmdEnv, false /* no throw */ ))
749 {
750 OUString line;
751 if (readLine( &line, "UNO_JAVA_CLASSPATH=", ucb_content,
752 RTL_TEXTENCODING_UTF8 ))
753 {
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())
758 {
760 nullptr, expandUnoRcTerm(token), xCmdEnv,
761 false /* no throw */ ))
762 {
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 );
768 }
769 }
770 }
771 while (index >= 0);
772 }
773 if (readLine( &line, "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())
779 {
780 if (token[ 0 ] == '?')
781 token = token.copy( 1 );
783 nullptr, expandUnoRcTerm(token), xCmdEnv,
784 false /* no throw */ ))
785 {
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 );
791 }
792 }
793 }
794 while (index >= 0);
795 }
796 if (readLine( &line, "UNO_SERVICES=", ucb_content,
797 RTL_TEXTENCODING_UTF8 ))
798 {
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;)
810 {
811 OUString token(line.getToken(0, ' ', i));
812 if (!token.isEmpty())
813 {
814 if (state == 1 && token.match("?$ORIGIN/"))
815 {
816 m_commonRDB_orig = token.copy(
817 RTL_CONSTASCII_LENGTH("?$ORIGIN/"));
818 state = 2;
819 }
820 else if ( state <= 2 && token == "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" )
821 {
822 state = 3;
823 }
824 else
825 {
826 if (token[0] == '?')
827 {
828 token = token.copy(1);
829 }
830 m_components.push_back(token);
831 state = 3;
832 }
833 }
834 }
835 }
836
837 // native rc:
839 &ucb_content,
840 makeURL( getCachePath(), getPlatformString() + "rc"),
841 xCmdEnv, false /* no throw */ )) {
842 if (readLine( &line, "UNO_SERVICES=", ucb_content,
843 RTL_TEXTENCODING_UTF8 )) {
844 m_nativeRDB_orig = line.copy(
845 sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 );
846 }
847 }
848 }
849 m_unorc_modified = false;
850 m_unorc_inited = true;
851}
852
853
854void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv )
855{
856 if (transientMode())
857 return;
859 return;
860
861 OStringBuffer buf;
862
863 buf.append("ORIGIN=");
864 OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
865 OString osOrigin = OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
866 buf.append(osOrigin);
867 buf.append(LF);
868
869 if (! m_jar_typelibs.empty())
870 {
871 auto iPos( m_jar_typelibs.cbegin() );
872 auto const iEnd( m_jar_typelibs.cend() );
873 buf.append( "UNO_JAVA_CLASSPATH=" );
874 while (iPos != iEnd) {
875 // encoded ASCII file-urls:
876 const OString item(
877 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
878 buf.append( item );
879 ++iPos;
880 if (iPos != iEnd)
881 buf.append( ' ' );
882 }
883 buf.append(LF);
884 }
885 if (! m_rdb_typelibs.empty())
886 {
887 auto iPos( m_rdb_typelibs.cbegin() );
888 auto const iEnd( m_rdb_typelibs.cend() );
889 buf.append( "UNO_TYPES=" );
890 while (iPos != iEnd) {
891 buf.append( '?' );
892 // encoded ASCII file-urls:
893 const OString item(
894 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
895 buf.append( item );
896 ++iPos;
897 if (iPos != iEnd)
898 buf.append( ' ' );
899 }
900 buf.append(LF);
901 }
902
903 // If we duplicated the common or native rdb then we must use those urls
904 //otherwise we use those of the original files. That is, m_commonRDB_orig
905 //and m_nativeRDB_orig;
906 OUString sCommonRDB(m_commonRDB.isEmpty() ? m_commonRDB_orig : m_commonRDB );
907 OUString sNativeRDB(m_nativeRDB.isEmpty() ? m_nativeRDB_orig : m_nativeRDB );
908
909 if (!sCommonRDB.isEmpty() || !sNativeRDB.isEmpty() ||
910 !m_components.empty())
911 {
912 buf.append( "UNO_SERVICES=" );
913 bool space = false;
914 if (!sCommonRDB.isEmpty())
915 {
916 buf.append( "?$ORIGIN/" );
917 buf.append( OUStringToOString(
918 sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
919 space = true;
920 }
921 if (!sNativeRDB.isEmpty())
922 {
923 if (space)
924 {
925 buf.append(' ');
926 }
927 buf.append( "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" );
928 space = true;
929
930 // write native rc:
931 OString buf2 =
932 "ORIGIN=" +
933 osOrigin +
934 OStringChar(LF) +
935 "UNO_SERVICES=?$ORIGIN/" +
936 OUStringToOString( sNativeRDB, RTL_TEXTENCODING_ASCII_US ) +
937 OStringChar(LF);
938
939 const Reference<io::XInputStream> xData(
940 ::xmlscript::createInputStream(
941 reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
942 buf2.getLength() ) );
943 ::ucbhelper::Content ucb_content(
944 makeURL( getCachePath(), getPlatformString() + "rc" ),
945 xCmdEnv, m_xComponentContext );
946 ucb_content.writeStream( xData, true /* replace existing */ );
947 }
948 for (auto const& component : m_components)
949 {
950 if (space)
951 {
952 buf.append(' ');
953 }
954 buf.append('?');
955 buf.append(OUStringToOString(component, RTL_TEXTENCODING_UTF8));
956 space = true;
957 }
958 buf.append(LF);
959 }
960
961 // write unorc:
962 const Reference<io::XInputStream> xData(
963 ::xmlscript::createInputStream(
964 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
965 buf.getLength() ) );
966 ::ucbhelper::Content ucb_content(
967 makeURL( getCachePath(), "unorc" ), xCmdEnv, m_xComponentContext );
968 ucb_content.writeStream( xData, true /* replace existing */ );
969
970 m_unorc_modified = false;
971}
972
973
974void BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
975 Reference<XCommandEnvironment> const & xCmdEnv )
976{
977 const OUString rcterm( dp_misc::makeRcTerm(url_) );
978 const ::osl::MutexGuard guard( m_aMutex );
979 unorc_verify_init( xCmdEnv );
980 std::deque<OUString> & rSet = getRcItemList(kind);
981 if (std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
982 rSet.push_front( rcterm ); // prepend to list, thus overriding
983 // write immediately:
984 m_unorc_modified = true;
985 unorc_flush( xCmdEnv );
986 }
987}
988
989
990void BackendImpl::removeFromUnoRc(
991 RcItem kind, OUString const & url_,
992 Reference<XCommandEnvironment> const & xCmdEnv )
993{
994 const OUString rcterm( dp_misc::makeRcTerm(url_) );
995 const ::osl::MutexGuard guard( m_aMutex );
996 unorc_verify_init( xCmdEnv );
997 std::deque<OUString> & aRcItemList = getRcItemList(kind);
998 aRcItemList.erase(std::remove(aRcItemList.begin(), aRcItemList.end(), rcterm), aRcItemList.end());
999 // write immediately:
1000 m_unorc_modified = true;
1001 unorc_flush( xCmdEnv );
1002}
1003
1004
1005bool BackendImpl::hasInUnoRc(
1006 RcItem kind, OUString const & url_ )
1007{
1008 const OUString rcterm( dp_misc::makeRcTerm(url_) );
1009 const ::osl::MutexGuard guard( m_aMutex );
1010 std::deque<OUString> const & rSet = getRcItemList(kind);
1011 return std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1012}
1013
1014css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext()
1015 const
1016{
1017 css::uno::Reference< css::uno::XComponentContext > rootContext(
1018 getComponentContext()->getValueByName("_root"),
1019 css::uno::UNO_QUERY);
1020 return rootContext.is() ? rootContext : getComponentContext();
1021}
1022
1023
1024void BackendImpl::releaseObject( OUString const & id )
1025{
1026 const ::osl::MutexGuard guard( m_aMutex );
1027 m_backendObjects.erase( id );
1028}
1029
1030
1031Reference<XInterface> BackendImpl::getObject( OUString const & id )
1032{
1033 const ::osl::MutexGuard guard( m_aMutex );
1034 const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1035 if (iFind == m_backendObjects.end())
1036 return Reference<XInterface>();
1037 else
1038 return iFind->second;
1039}
1040
1041
1042Reference<XInterface> BackendImpl::insertObject(
1043 OUString const & id, Reference<XInterface> const & xObject )
1044{
1045 const ::osl::MutexGuard guard( m_aMutex );
1046 const std::pair<t_string2object::iterator, bool> insertion(
1047 m_backendObjects.emplace( id, xObject ) );
1048 return insertion.first->second;
1049}
1050
1051
1052Reference<XComponentContext> raise_uno_process(
1053 Reference<XComponentContext> const & xContext,
1054 ::rtl::Reference<AbortChannel> const & abortChannel )
1055{
1056 OSL_ASSERT( xContext.is() );
1057
1058 OUString url( util::theMacroExpander::get(xContext)->expandMacros( "$URE_BIN_DIR/uno" ) );
1059
1060 const OUString connectStr = "uno:pipe,name=" + generateRandomPipeId() + ";urp;uno.ComponentContext";
1061
1062 // raise core UNO process to register/run a component,
1063 // javavm service uses unorc next to executable to retrieve deployed
1064 // jar typelibs
1065
1066 std::vector<OUString> args{
1067#if OSL_DEBUG_LEVEL == 0
1068 "--quiet",
1069#endif
1070 "--singleaccept",
1071 "-u",
1072 connectStr,
1073 // don't inherit from unorc:
1074 "-env:INIFILENAME=" };
1075
1076 //now add the bootstrap variables which were supplied on the command line
1077 std::vector<OUString> bootvars = getCmdBootstrapVariables();
1078 args.insert(args.end(), bootvars.begin(), bootvars.end());
1079
1080 oslProcess hProcess;
1081 try {
1082 hProcess = raiseProcess(
1084 }
1085 catch (...) {
1086 OUStringBuffer sMsg = "error starting process: " + url;
1087 for(const auto& arg : args)
1088 sMsg.append(" " + arg);
1089 throw uno::RuntimeException(sMsg.makeStringAndClear());
1090 }
1091 try {
1092 return Reference<XComponentContext>(
1093 resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1094 UNO_QUERY_THROW );
1095 }
1096 catch (...) {
1097 // try to terminate process:
1098 if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1099 {
1100 OSL_ASSERT( false );
1101 }
1102 throw;
1103 }
1104}
1105
1106void extractComponentData(
1107 css::uno::Reference< css::uno::XComponentContext > const & context,
1108 css::uno::Reference< css::registry::XRegistryKey > const & registry,
1109 ComponentBackendDb::Data * data,
1110 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1111 css::uno::Reference< css::loader::XImplementationLoader > const &
1112 componentLoader,
1113 OUString const & componentUrl)
1114{
1115 OSL_ASSERT(
1116 context.is() && registry.is() && data != nullptr && componentLoader.is());
1117 OUString registryName(registry->getKeyName());
1118 sal_Int32 prefix = registryName.getLength();
1119 if (!registryName.endsWith("/")) {
1120 prefix += RTL_CONSTASCII_LENGTH("/");
1121 }
1122 const css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1123 keys(registry->openKeys());
1124 css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1125 context->getServiceManager(), css::uno::UNO_SET_THROW);
1126 for (css::uno::Reference< css::registry::XRegistryKey > const & key : keys) {
1127 OUString name(key->getKeyName().copy(prefix));
1128 data->implementationNames.push_back(name);
1129 css::uno::Reference< css::registry::XRegistryKey > singletons(
1130 key->openKey("UNO/SINGLETONS"));
1131 if (singletons.is()) {
1132 sal_Int32 prefix2 = key->getKeyName().getLength() +
1133 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1134 const css::uno::Sequence<
1135 css::uno::Reference< css::registry::XRegistryKey > >
1136 singletonKeys(singletons->openKeys());
1137 for (css::uno::Reference< css::registry::XRegistryKey > const & singletonKey : singletonKeys) {
1138 data->singletons.emplace_back(
1139 singletonKey->getKeyName().copy(prefix2), name);
1140 }
1141 }
1142 if (factories != nullptr) {
1143 factories->push_back(
1144 componentLoader->activate(
1145 name, OUString(), componentUrl, key));
1146 }
1147 }
1148}
1149
1150void BackendImpl::ComponentPackageImpl::getComponentInfo(
1151 ComponentBackendDb::Data * data,
1152 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1153 Reference<XComponentContext> const & xContext )
1154{
1155 const Reference<loader::XImplementationLoader> xLoader(
1156 xContext->getServiceManager()->createInstanceWithContext(
1157 m_loader, xContext ), UNO_QUERY );
1158 if (! xLoader.is())
1159 {
1160 throw css::deployment::DeploymentException(
1161 "cannot instantiate loader " + m_loader,
1162 static_cast< OWeakObject * >(this), Any());
1163 }
1164
1165 // HACK: highly dependent on stoc/source/servicemanager
1166 // and stoc/source/implreg implementation which rely on the same
1167 // services.rdb format!
1168 // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1169 // writeRegistryInfo, however, but are known, fixed values here, so
1170 // can be passed into extractComponentData
1171 OUString url(getURL());
1172 const Reference<registry::XSimpleRegistry> xMemReg(
1173 xContext->getServiceManager()->createInstanceWithContext(
1174 "com.sun.star.registry.SimpleRegistry", xContext ),
1175 UNO_QUERY_THROW );
1176 xMemReg->open( OUString() /* in mem */, false, true );
1177 xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1178 extractComponentData(
1179 xContext, xMemReg->getRootKey(), data, factories, xLoader, url);
1180}
1181
1182void BackendImpl::ComponentPackageImpl::componentLiveInsertion(
1183 ComponentBackendDb::Data const & data,
1184 std::vector< css::uno::Reference< css::uno::XInterface > > const &
1185 factories)
1186{
1187 css::uno::Reference< css::uno::XComponentContext > rootContext(
1188 getMyBackend()->getRootContext());
1189 css::uno::Reference< css::container::XSet > set(
1190 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1191 std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1192 factory(factories.begin());
1193 for (auto const& implementationName : data.implementationNames)
1194 {
1195 try {
1196 set->insert(css::uno::Any(*factory++));
1197 } catch (const container::ElementExistException &) {
1198 SAL_WARN("desktop.deployment", "implementation already registered " << implementationName);
1199 }
1200 }
1201 if (data.singletons.empty()) return;
1202
1203 css::uno::Reference< css::container::XNameContainer > cont(
1204 rootContext, css::uno::UNO_QUERY_THROW);
1205 for (auto const& singleton : data.singletons)
1206 {
1207 OUString name("/singletons/" + singleton.first);
1208 //TODO: Update should be atomic:
1209 try {
1210 cont->removeByName( name + "/arguments");
1211 } catch (const container::NoSuchElementException &) {}
1212 try {
1213 cont->insertByName( name + "/service", css::uno::Any(singleton.second));
1214 } catch (const container::ElementExistException &) {
1215 cont->replaceByName( name + "/service", css::uno::Any(singleton.second));
1216 }
1217 try {
1218 cont->insertByName(name, css::uno::Any());
1219 } catch (const container::ElementExistException &) {
1220 SAL_WARN("desktop.deployment", "singleton already registered " << singleton.first);
1221 cont->replaceByName(name, css::uno::Any());
1222 }
1223 }
1224}
1225
1226void BackendImpl::ComponentPackageImpl::componentLiveRemoval(
1227 ComponentBackendDb::Data const & data)
1228{
1229 css::uno::Reference< css::uno::XComponentContext > rootContext(
1230 getMyBackend()->getRootContext());
1231 css::uno::Reference< css::container::XSet > set(
1232 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1233 for (auto const& implementationName : data.implementationNames)
1234 {
1235 try {
1236 set->remove(css::uno::Any(implementationName));
1237 } catch (const css::container::NoSuchElementException &) {
1238 // ignore if factory has not been live deployed
1239 }
1240 }
1241 if (data.singletons.empty())
1242 return;
1243
1244 css::uno::Reference< css::container::XNameContainer > cont(
1245 rootContext, css::uno::UNO_QUERY_THROW);
1246 for (auto const& singleton : data.singletons)
1247 {
1248 OUString name("/singletons/" + singleton.first);
1249 //TODO: Removal should be atomic:
1250 try {
1251 cont->removeByName(name);
1252 } catch (const container::NoSuchElementException &) {}
1253 try {
1254 cont->removeByName( name + "/service" );
1255 } catch (const container::NoSuchElementException &) {}
1256 try {
1257 cont->removeByName( name + "/arguments" );
1258 } catch (const container::NoSuchElementException &) {}
1259 }
1260}
1261
1262// Package
1263
1264//We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1265//And it also shows the problem if another extension has overwritten an implementation
1266//entry, because it contains the same service implementation
1267beans::Optional< beans::Ambiguous<sal_Bool> >
1268BackendImpl::ComponentPackageImpl::isRegistered_(
1269 ::osl::ResettableMutexGuard &,
1270 ::rtl::Reference<AbortChannel> const & abortChannel,
1271 Reference<XCommandEnvironment> const & )
1272{
1273 if (m_registered == Reg::Uninit)
1274 {
1275 m_registered = Reg::NotRegistered;
1276 const Reference<registry::XSimpleRegistry> xRDB( getRDB() );
1277 if (xRDB.is())
1278 {
1279 bool bAmbiguousComponentName = false;
1280 // lookup rdb for location URL:
1281 const Reference<registry::XRegistryKey> xRootKey(
1282 xRDB->getRootKey() );
1283 const Reference<registry::XRegistryKey> xImplKey(
1284 xRootKey->openKey( "IMPLEMENTATIONS" ) );
1285 Sequence<OUString> implNames;
1286 if (xImplKey.is() && xImplKey->isValid())
1287 implNames = xImplKey->getKeyNames();
1288 OUString const * pImplNames = implNames.getConstArray();
1289 sal_Int32 pos = implNames.getLength();
1290 for ( ; pos--; )
1291 {
1292 checkAborted( abortChannel );
1293 const OUString key(
1294 pImplNames[ pos ] + "/UNO/LOCATION" );
1295 const Reference<registry::XRegistryKey> xKey(
1296 xRootKey->openKey(key) );
1297 if (xKey.is() && xKey->isValid())
1298 {
1299 const OUString location( xKey->getAsciiValue() );
1300 if (location.equalsIgnoreAsciiCase( getURL() ))
1301 {
1302 break;
1303 }
1304 else
1305 {
1306 //try to match only the file name
1307 OUString thisUrl(getURL());
1308 std::u16string_view thisFileName(thisUrl.subView(thisUrl.lastIndexOf('/')));
1309
1310 std::u16string_view locationFileName(location.subView(location.lastIndexOf('/')));
1311 if (o3tl::equalsIgnoreAsciiCase(locationFileName, thisFileName))
1312 bAmbiguousComponentName = true;
1313 }
1314 }
1315 }
1316 if (pos >= 0)
1317 m_registered = Reg::Registered;
1318 else if (bAmbiguousComponentName)
1319 m_registered = Reg::MaybeRegistered;
1320 }
1321 }
1322
1323 //Different extensions can use the same service implementations. Then the extensions
1324 //which was installed last will overwrite the one from the other extension. That is
1325 //the registry will contain the path (the location) of the library or jar of the
1326 //second extension. In this case isRegistered called for the lib of the first extension
1327 //would return "not registered". That would mean that during uninstallation
1328 //XPackage::registerPackage is not called, because it just was not registered. This is,
1329 //however, necessary for jar files. Registering and unregistering update
1330 //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1331 //Therefore, we will return always "is ambiguous" if the path of this component cannot
1332 //be found in the registry and if there is another path and both have the same file name (but
1333 //the rest of the path is different).
1334 //If the caller cannot precisely determine that this package was registered, then it must
1335 //call registerPackage.
1336 bool bAmbiguous = m_registered == Reg::Void // Reg::Void == we are in the progress of unregistration
1337 || m_registered == Reg::MaybeRegistered;
1338 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1339 true /* IsPresent */,
1340 beans::Ambiguous<sal_Bool>(
1341 m_registered == Reg::Registered, bAmbiguous) );
1342}
1343
1344
1345void BackendImpl::ComponentPackageImpl::processPackage_(
1346 ::osl::ResettableMutexGuard &,
1347 bool doRegisterPackage,
1348 bool startup,
1349 ::rtl::Reference<AbortChannel> const & abortChannel,
1350 Reference<XCommandEnvironment> const & xCmdEnv )
1351{
1352 BackendImpl * that = getMyBackend();
1353 OUString url(getURL());
1354 if (doRegisterPackage) {
1355 ComponentBackendDb::Data data;
1356 css::uno::Reference< css::uno::XComponentContext > context;
1357 if (startup) {
1358 context = that->getComponentContext();
1359 } else {
1360 context.set(that->getObject(url), css::uno::UNO_QUERY);
1361 if (!context.is()) {
1362 context.set(
1363 that->insertObject(
1364 url,
1365 raise_uno_process(
1366 that->getComponentContext(), abortChannel)),
1367 css::uno::UNO_QUERY_THROW);
1368 }
1369 }
1370 css::uno::Reference< css::registry::XImplementationRegistration> impreg(
1371 context->getServiceManager()->createInstanceWithContext(
1372 "com.sun.star.registry.ImplementationRegistration",
1373 context),
1374 css::uno::UNO_QUERY_THROW);
1375 css::uno::Reference< css::registry::XSimpleRegistry > rdb(getRDB());
1376 impreg->registerImplementation(m_loader, url, rdb);
1377 // Only write to unorc after successful registration; it may fail if
1378 // there is no suitable java
1379 if (m_loader == "com.sun.star.loader.Java2" && !jarManifestHeaderPresent(url, "UNO-Type-Path", xCmdEnv))
1380 {
1381 that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1382 data.javaTypeLibrary = true;
1383 }
1384 std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1385 getComponentInfo(&data, startup ? nullptr : &factories, context);
1386 if (!startup) {
1387 try {
1388 componentLiveInsertion(data, factories);
1389 } catch (css::uno::Exception &) {
1390 TOOLS_INFO_EXCEPTION("desktop.deployment", "caught");
1391 try {
1392 impreg->revokeImplementation(url, rdb);
1393 } catch (css::uno::RuntimeException &) {
1394 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignored");
1395 }
1396 throw;
1397 }
1398 }
1399 m_registered = Reg::Registered;
1400 that->addDataToDb(url, data);
1401 } else { // revoke
1402 m_registered = Reg::Void;
1403 ComponentBackendDb::Data data(that->readDataFromDb(url));
1404 css::uno::Reference< css::uno::XComponentContext > context(
1405 that->getObject(url), css::uno::UNO_QUERY);
1406 bool remoteContext = context.is();
1407 if (!remoteContext) {
1408 context = that->getComponentContext();
1409 }
1410 if (!startup) {
1411 componentLiveRemoval(data);
1412 }
1413 css::uno::Reference< css::registry::XImplementationRegistration >(
1414 context->getServiceManager()->createInstanceWithContext(
1415 "com.sun.star.registry.ImplementationRegistration",
1416 context),
1417 css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1418 if (data.javaTypeLibrary) {
1419 that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1420 }
1421 if (remoteContext) {
1422 that->releaseObject(url);
1423 }
1424 m_registered = Reg::NotRegistered;
1425 getMyBackend()->revokeEntryFromDb(url);
1426 }
1427}
1428
1429BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1431 OUString const & url, OUString const & name,
1432 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1433 bool jarFile, bool bRemoved, OUString const & identifier)
1434 : Package( myBackend, url, name, name /* display-name */,
1435 xPackageType, bRemoved, identifier),
1436 m_jarFile( jarFile )
1437{
1438}
1439
1440// Package
1441BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1442{
1443 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1444 if (nullptr == pBackend)
1445 {
1446 //May throw a DisposedException
1447 check();
1448 //We should never get here...
1449 throw RuntimeException( "Failed to get the BackendImpl",
1450 static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1451 }
1452 return pBackend;
1453}
1454
1455beans::Optional< beans::Ambiguous<sal_Bool> >
1456BackendImpl::TypelibraryPackageImpl::isRegistered_(
1457 ::osl::ResettableMutexGuard &,
1459 Reference<XCommandEnvironment> const & )
1460{
1461 BackendImpl * that = getMyBackend();
1462 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1463 true /* IsPresent */,
1464 beans::Ambiguous<sal_Bool>(
1465 that->hasInUnoRc(
1466 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1467 false /* IsAmbiguous */ ) );
1468}
1469
1470
1471void BackendImpl::TypelibraryPackageImpl::processPackage_(
1472 ::osl::ResettableMutexGuard &,
1473 bool doRegisterPackage,
1474 bool /*startup*/,
1476 Reference<XCommandEnvironment> const & xCmdEnv )
1477{
1478 BackendImpl * that = getMyBackend();
1479 const OUString url( getURL() );
1480
1481 if (doRegisterPackage)
1482 {
1483 // live insertion:
1484 if (m_jarFile) {
1485 // xxx todo add to classpath at runtime: ???
1486 //SB: It is probably not worth it to add the live inserted type
1487 // library JAR to the UnoClassLoader in the soffice process. Any
1488 // live inserted component JAR that might reference this type
1489 // library JAR runs in its own uno process, so there is probably no
1490 // Java code in the soffice process that would see any UNO types
1491 // introduced by this type library JAR.
1492 }
1493 else // RDB:
1494 {
1495 css::uno::Reference< css::container::XSet >(
1496 that->getComponentContext()->getValueByName(
1497 "/singletons"
1498 "/com.sun.star.reflection.theTypeDescriptionManager"),
1499 css::uno::UNO_QUERY_THROW)->insert(
1500 css::uno::Any(expandUnoRcUrl(url)));
1501 }
1502
1503 that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1504 url, xCmdEnv );
1505 }
1506 else // revokePackage()
1507 {
1508 that->removeFromUnoRc(
1509 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1510
1511 // revoking types at runtime, possible, sensible?
1512 if (!m_jarFile) {
1513 css::uno::Reference< css::container::XSet >(
1514 that->getComponentContext()->getValueByName(
1515 "/singletons"
1516 "/com.sun.star.reflection.theTypeDescriptionManager"),
1517 css::uno::UNO_QUERY_THROW)->remove(
1518 css::uno::Any(expandUnoRcUrl(url)));
1519 }
1520 }
1521}
1522
1523BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl(
1525 OUString const & url, OUString const & name,
1526 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1527 bool bRemoved, OUString const & identifier, OUString platform)
1528 : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier)
1529 , m_aPlatform(std::move(platform))
1530{
1531 OSL_PRECOND(bRemoved, "this class can only be used for removing packages!");
1532}
1533
1534BackendImpl *
1535BackendImpl::OtherPlatformPackageImpl::getMyBackend() const
1536{
1537 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1538 if (nullptr == pBackend)
1539 {
1540 //Throws a DisposedException
1541 check();
1542 //We should never get here...
1543 throw RuntimeException("Failed to get the BackendImpl",
1544 static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this)));
1545 }
1546 return pBackend;
1547}
1548
1549Reference<registry::XSimpleRegistry>
1550BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const
1551{
1552 OUString const aRDB(m_aPlatform + ".rdb");
1553 OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB));
1554
1555 Reference<registry::XSimpleRegistry> xRegistry;
1556
1557 try
1558 {
1559 xRegistry.set(
1560 impl_createInstance("com.sun.star.registry.SimpleRegistry"),
1561 UNO_QUERY)
1562 ;
1563 if (xRegistry.is())
1564 xRegistry->open(expandUnoRcUrl(aRDBPath), false, false);
1565 }
1566 catch (registry::InvalidRegistryException const&)
1567 {
1568 // If the registry does not exist, we do not need to bother at all
1569 xRegistry.set(nullptr);
1570 }
1571
1572 SAL_WARN_IF( !xRegistry.is(), "desktop.deployment", "could not create registry for the package's platform");
1573 return xRegistry;
1574}
1575
1576Reference<XInterface>
1577BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService)
1578const
1579{
1580 Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext());
1581 OSL_ASSERT(xContext.is());
1582 Reference<XInterface> xService;
1583 if (xContext.is())
1584 xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext));
1585 return xService;
1586}
1587
1588beans::Optional<beans::Ambiguous<sal_Bool> >
1589BackendImpl::OtherPlatformPackageImpl::isRegistered_(
1590 ::osl::ResettableMutexGuard& /* guard */,
1591 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1592 Reference<XCommandEnvironment> const& /* xCmdEnv */ )
1593{
1594 return beans::Optional<beans::Ambiguous<sal_Bool> >(true,
1595 beans::Ambiguous<sal_Bool>(true, false));
1596}
1597
1598void
1599BackendImpl::OtherPlatformPackageImpl::processPackage_(
1600 ::osl::ResettableMutexGuard& /* guard */,
1601 bool bRegisterPackage,
1602 bool /* bStartup */,
1603 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1604 Reference<XCommandEnvironment> const& /* xCmdEnv */)
1605{
1606 OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!");
1607
1608 OUString const aURL(getURL());
1609
1610 Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB());
1611 Reference<registry::XImplementationRegistration> const xImplReg(
1612 impl_createInstance("com.sun.star.registry.ImplementationRegistration"),
1613 UNO_QUERY)
1614 ;
1615 if (xImplReg.is() && xServicesRDB.is())
1616 xImplReg->revokeImplementation(aURL, xServicesRDB);
1617 if (xServicesRDB.is())
1618 xServicesRDB->close();
1619
1620 getMyBackend()->revokeEntryFromDb(aURL);
1621}
1622
1623BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1624{
1625 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1626 if (nullptr == pBackend)
1627 {
1628 //Throws a DisposedException
1629 check();
1630 //We should never get here...
1631 throw RuntimeException("Failed to get the BackendImpl",
1632 static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1633 }
1634 return pBackend;
1635}
1636
1637beans::Optional< beans::Ambiguous<sal_Bool> >
1638BackendImpl::ComponentsPackageImpl::isRegistered_(
1639 ::osl::ResettableMutexGuard &,
1641 Reference<XCommandEnvironment> const & )
1642{
1643 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1644 true,
1645 beans::Ambiguous<sal_Bool>(
1646 getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1647}
1648
1649void BackendImpl::ComponentsPackageImpl::processPackage_(
1650 ::osl::ResettableMutexGuard &,
1651 bool doRegisterPackage,
1652 bool startup,
1653 ::rtl::Reference<AbortChannel> const & abortChannel,
1654 Reference<XCommandEnvironment> const & xCmdEnv )
1655{
1656 BackendImpl * that = getMyBackend();
1657 OUString url(getURL());
1658 if (doRegisterPackage) {
1659 if (!startup) {
1660 css::uno::Reference< css::uno::XComponentContext > context(
1661 that->getObject(url), css::uno::UNO_QUERY);
1662 if (!context.is()) {
1663 context.set(
1664 that->insertObject(
1665 url,
1666 raise_uno_process(
1667 that->getComponentContext(), abortChannel)),
1668 css::uno::UNO_QUERY_THROW);
1669 }
1670 // This relies on the root component context's service manager
1671 // supporting the extended XSet semantics:
1672 css::uno::Sequence< css::beans::NamedValue > args
1673 {
1674 { "uri", css::uno::Any(expandUnoRcUrl(url)) },
1675 { "component-context", css::uno::Any(context) }
1676 };
1677 css::uno::Reference< css::container::XSet > smgr(
1678 that->getRootContext()->getServiceManager(),
1679 css::uno::UNO_QUERY_THROW);
1680 smgr->insert(css::uno::Any(args));
1681 }
1682 that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1683 } else { // revoke
1684 that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1685 if (!startup) {
1686 // This relies on the root component context's service manager
1687 // supporting the extended XSet semantics:
1688 css::uno::Sequence< css::beans::NamedValue > args { { "uri", css::uno::Any(expandUnoRcUrl(url)) } };
1689 css::uno::Reference< css::container::XSet > smgr(
1690 that->getRootContext()->getServiceManager(),
1691 css::uno::UNO_QUERY_THROW);
1692 smgr->remove(css::uno::Any(args));
1693 }
1694 that->releaseObject(url);
1695 that->revokeEntryFromDb(url); // in case it got added with old code
1696 }
1697}
1698
1699BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1701 OUString const & url, OUString const & name,
1702 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1703 bool bRemoved, OUString const & identifier)
1704 : Package( myBackend, url, name, name /* display-name */,
1705 xPackageType, bRemoved, identifier)
1706{}
1707
1708} // anon namespace
1709
1710} // namespace dp_registry
1711
1712
1713extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1715 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
1716{
1717 return cppu::acquire(new dp_registry::backend::component::BackendImpl(args, context));
1718}
1719
1720/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool parse(OUString const &rMediaType, OUString &rType, OUString &rSubType, INetContentTypeParameterList *pParameters=nullptr)
virtual void SAL_CALL disposing() override
Definition: dp_backend.cxx:116
css::uno::Reference< css::ucb::XContent > get() const
void writeStream(const css::uno::Reference< css::io::XInputStream > &rStream, bool bReplaceExisting)
Any value
#define SAL_DLLEXTENSION
#define TOOLS_WARN_EXCEPTION(area, stream)
#define TOOLS_INFO_EXCEPTION(area, stream)
URL aURL
bool bSwitchedRdbFiles
OUString const m_aPlatform
OUString m_nativeRDB
std::deque< OUString > m_rdb_typelibs
OUString m_commonRDB
const Reference< deployment::XPackageTypeInfo > m_xPythonComponentTypeInfo
OUString m_nativeRDB_orig
const Reference< deployment::XPackageTypeInfo > m_xRDBTypelibTypeInfo
Reference< registry::XSimpleRegistry > m_xCommonRDB
const Reference< deployment::XPackageTypeInfo > m_xComponentsTypeInfo
Sequence< Reference< deployment::XPackageTypeInfo > > m_typeInfos
std::deque< OUString > m_jar_typelibs
const OUString m_loader
t_string2object m_backendObjects
std::deque< OUString > m_components
const bool m_jarFile
Reference< registry::XSimpleRegistry > m_xNativeRDB
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_deployment_component_PackageRegistryBackend_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &args)
Reg m_registered
const Reference< deployment::XPackageTypeInfo > m_xJavaTypelibTypeInfo
std::unique_ptr< ComponentBackendDb > m_backendDb
const Reference< deployment::XPackageTypeInfo > m_xJavaComponentTypeInfo
bool m_unorc_inited
const Reference< deployment::XPackageTypeInfo > m_xDynComponentTypeInfo
OUString m_commonRDB_orig
bool m_unorc_modified
Reference< XComponentContext > const m_xComponentContext
OUString DpResId(TranslateId aId)
Definition: dp_misc.cxx:554
float u
const char * name
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2435
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
void set(css::uno::UnoInterfaceReference const &value)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OUString expandMacros(OUString const &text)
OUString makeRcTerm(OUString const &url)
Definition: dp_misc.cxx:298
OUString expandUnoRcUrl(OUString const &url)
Definition: dp_misc.cxx:314
OUString makeURL(OUString const &baseURL, OUString const &relPath_)
appends a relative path to a url.
Definition: dp_misc.cxx:250
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readLine(OUString *res, OUString const &startingWith, ::ucbhelper::Content &ucb_content, rtl_TextEncoding textenc)
Definition: dp_ucb.cxx:200
Reference< XInterface > resolveUnoURL(OUString const &connectString, Reference< XComponentContext > const &xLocalContext, AbortChannel const *abortChannel)
Definition: dp_misc.cxx:430
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
OUString generateRandomPipeId()
Definition: dp_misc.cxx:411
OUString expandUnoRcTerm(OUString const &term_)
Definition: dp_misc.cxx:291
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool platform_fits(std::u16string_view platform_string)
oslProcess raiseProcess(OUString const &appURL, Sequence< OUString > const &args)
Definition: dp_misc.cxx:375
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString const & getPlatformString()
const char LF
Definition: dp_misc.h:35
constexpr OUStringLiteral BACKEND_SERVICE_NAME
Definition: dp_backend.h:41
int i
line
index
def check(model)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::u16string_view trim(std::u16string_view str)
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
loader
static SfxItemSet & rSet
::boost::spirit::classic::rule< ScannerT > identifier
unsigned char sal_Bool
signed char sal_Int8
ResultType type
size_t pos