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>
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, std::u16string_view 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, u"RegistrationClassName", xCmdEnv ))
625 mediaType = "application/vnd.sun.star.uno-component;type=Java";
626 if (mediaType.isEmpty())
627 mediaType = "application/vnd.sun.star.uno-typelibrary;type=Java";
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, u"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, u"UNO_TYPES=", ucb_content,
774 RTL_TEXTENCODING_UTF8 )) {
775 sal_Int32 index = sizeof ("UNO_TYPES=") - 1;
776 do {
777 OUString token( o3tl::trim(o3tl::getToken(line, 0, ' ', index )) );
778 if (!token.isEmpty())
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, u"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, u"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 OUString sOrigin = dp_misc::makeRcTerm(m_cachePath);
862 OString osOrigin = OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8);
863 OStringBuffer buf("ORIGIN=" + osOrigin + OStringChar(LF));
864
865 if (! m_jar_typelibs.empty())
866 {
867 auto iPos( m_jar_typelibs.cbegin() );
868 auto const iEnd( m_jar_typelibs.cend() );
869 buf.append( "UNO_JAVA_CLASSPATH=" );
870 while (iPos != iEnd) {
871 // encoded ASCII file-urls:
872 const OString item(
873 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
874 buf.append( item );
875 ++iPos;
876 if (iPos != iEnd)
877 buf.append( ' ' );
878 }
879 buf.append(LF);
880 }
881 if (! m_rdb_typelibs.empty())
882 {
883 auto iPos( m_rdb_typelibs.cbegin() );
884 auto const iEnd( m_rdb_typelibs.cend() );
885 buf.append( "UNO_TYPES=" );
886 while (iPos != iEnd) {
887 buf.append( '?' );
888 // encoded ASCII file-urls:
889 const OString item(
890 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
891 buf.append( item );
892 ++iPos;
893 if (iPos != iEnd)
894 buf.append( ' ' );
895 }
896 buf.append(LF);
897 }
898
899 // If we duplicated the common or native rdb then we must use those urls
900 //otherwise we use those of the original files. That is, m_commonRDB_orig
901 //and m_nativeRDB_orig;
902 OUString sCommonRDB(m_commonRDB.isEmpty() ? m_commonRDB_orig : m_commonRDB );
903 OUString sNativeRDB(m_nativeRDB.isEmpty() ? m_nativeRDB_orig : m_nativeRDB );
904
905 if (!sCommonRDB.isEmpty() || !sNativeRDB.isEmpty() ||
906 !m_components.empty())
907 {
908 buf.append( "UNO_SERVICES=" );
909 bool space = false;
910 if (!sCommonRDB.isEmpty())
911 {
912 buf.append( "?$ORIGIN/"
913 + OUStringToOString( sCommonRDB, RTL_TEXTENCODING_ASCII_US ) );
914 space = true;
915 }
916 if (!sNativeRDB.isEmpty())
917 {
918 if (space)
919 {
920 buf.append(' ');
921 }
922 buf.append( "${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}" );
923 space = true;
924
925 // write native rc:
926 OString buf2 =
927 "ORIGIN=" +
928 osOrigin +
929 OStringChar(LF) +
930 "UNO_SERVICES=?$ORIGIN/" +
931 OUStringToOString( sNativeRDB, RTL_TEXTENCODING_ASCII_US ) +
932 OStringChar(LF);
933
934 const Reference<io::XInputStream> xData(
935 ::xmlscript::createInputStream(
936 reinterpret_cast<sal_Int8 const *>(buf2.getStr()),
937 buf2.getLength() ) );
938 ::ucbhelper::Content ucb_content(
939 makeURL( getCachePath(), getPlatformString() + "rc" ),
940 xCmdEnv, m_xComponentContext );
941 ucb_content.writeStream( xData, true /* replace existing */ );
942 }
943 for (auto const& component : m_components)
944 {
945 if (space)
946 {
947 buf.append(' ');
948 }
949 buf.append("?" + OUStringToOString(component, RTL_TEXTENCODING_UTF8));
950 space = true;
951 }
952 buf.append(LF);
953 }
954
955 // write unorc:
956 const Reference<io::XInputStream> xData(
957 ::xmlscript::createInputStream(
958 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
959 buf.getLength() ) );
960 ::ucbhelper::Content ucb_content(
961 makeURL( getCachePath(), "unorc" ), xCmdEnv, m_xComponentContext );
962 ucb_content.writeStream( xData, true /* replace existing */ );
963
964 m_unorc_modified = false;
965}
966
967
968void BackendImpl::addToUnoRc( RcItem kind, OUString const & url_,
969 Reference<XCommandEnvironment> const & xCmdEnv )
970{
971 const OUString rcterm( dp_misc::makeRcTerm(url_) );
972 const ::osl::MutexGuard guard( m_aMutex );
973 unorc_verify_init( xCmdEnv );
974 std::deque<OUString> & rSet = getRcItemList(kind);
975 if (std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
976 rSet.push_front( rcterm ); // prepend to list, thus overriding
977 // write immediately:
978 m_unorc_modified = true;
979 unorc_flush( xCmdEnv );
980 }
981}
982
983
984void BackendImpl::removeFromUnoRc(
985 RcItem kind, OUString const & url_,
986 Reference<XCommandEnvironment> const & xCmdEnv )
987{
988 const OUString rcterm( dp_misc::makeRcTerm(url_) );
989 const ::osl::MutexGuard guard( m_aMutex );
990 unorc_verify_init( xCmdEnv );
991 std::deque<OUString> & aRcItemList = getRcItemList(kind);
992 aRcItemList.erase(std::remove(aRcItemList.begin(), aRcItemList.end(), rcterm), aRcItemList.end());
993 // write immediately:
994 m_unorc_modified = true;
995 unorc_flush( xCmdEnv );
996}
997
998
999bool BackendImpl::hasInUnoRc(
1000 RcItem kind, OUString const & url_ )
1001{
1002 const OUString rcterm( dp_misc::makeRcTerm(url_) );
1003 const ::osl::MutexGuard guard( m_aMutex );
1004 std::deque<OUString> const & rSet = getRcItemList(kind);
1005 return std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end();
1006}
1007
1008css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext()
1009 const
1010{
1011 css::uno::Reference< css::uno::XComponentContext > rootContext(
1012 getComponentContext()->getValueByName("_root"),
1013 css::uno::UNO_QUERY);
1014 return rootContext.is() ? rootContext : getComponentContext();
1015}
1016
1017
1018void BackendImpl::releaseObject( OUString const & id )
1019{
1020 const ::osl::MutexGuard guard( m_aMutex );
1021 m_backendObjects.erase( id );
1022}
1023
1024
1025Reference<XInterface> BackendImpl::getObject( OUString const & id )
1026{
1027 const ::osl::MutexGuard guard( m_aMutex );
1028 const t_string2object::const_iterator iFind( m_backendObjects.find( id ) );
1029 if (iFind == m_backendObjects.end())
1030 return Reference<XInterface>();
1031 else
1032 return iFind->second;
1033}
1034
1035
1036Reference<XInterface> BackendImpl::insertObject(
1037 OUString const & id, Reference<XInterface> const & xObject )
1038{
1039 const ::osl::MutexGuard guard( m_aMutex );
1040 const std::pair<t_string2object::iterator, bool> insertion(
1041 m_backendObjects.emplace( id, xObject ) );
1042 return insertion.first->second;
1043}
1044
1045
1046Reference<XComponentContext> raise_uno_process(
1047 Reference<XComponentContext> const & xContext,
1048 ::rtl::Reference<AbortChannel> const & abortChannel )
1049{
1050 OSL_ASSERT( xContext.is() );
1051
1052 OUString url( util::theMacroExpander::get(xContext)->expandMacros( "$URE_BIN_DIR/uno" ) );
1053
1054 const OUString connectStr = "uno:pipe,name=" + generateRandomPipeId() + ";urp;uno.ComponentContext";
1055
1056 // raise core UNO process to register/run a component,
1057 // javavm service uses unorc next to executable to retrieve deployed
1058 // jar typelibs
1059
1060 std::vector<OUString> args{
1061#if OSL_DEBUG_LEVEL == 0
1062 "--quiet",
1063#endif
1064 "--singleaccept",
1065 "-u",
1066 connectStr,
1067 // don't inherit from unorc:
1068 "-env:INIFILENAME=" };
1069
1070 //now add the bootstrap variables which were supplied on the command line
1071 std::vector<OUString> bootvars = getCmdBootstrapVariables();
1072 args.insert(args.end(), bootvars.begin(), bootvars.end());
1073
1074 oslProcess hProcess;
1075 try {
1076 hProcess = raiseProcess(
1078 }
1079 catch (...) {
1080 OUStringBuffer sMsg = "error starting process: " + url;
1081 for(const auto& arg : args)
1082 sMsg.append(" " + arg);
1083 throw uno::RuntimeException(sMsg.makeStringAndClear());
1084 }
1085 try {
1086 return Reference<XComponentContext>(
1087 resolveUnoURL( connectStr, xContext, abortChannel.get() ),
1088 UNO_QUERY_THROW );
1089 }
1090 catch (...) {
1091 // try to terminate process:
1092 if ( osl_terminateProcess( hProcess ) != osl_Process_E_None )
1093 {
1094 OSL_ASSERT( false );
1095 }
1096 throw;
1097 }
1098}
1099
1100void extractComponentData(
1101 css::uno::Reference< css::uno::XComponentContext > const & context,
1102 css::uno::Reference< css::registry::XRegistryKey > const & registry,
1103 ComponentBackendDb::Data * data,
1104 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1105 css::uno::Reference< css::loader::XImplementationLoader > const &
1106 componentLoader,
1107 OUString const & componentUrl)
1108{
1109 OSL_ASSERT(
1110 context.is() && registry.is() && data != nullptr && componentLoader.is());
1111 OUString registryName(registry->getKeyName());
1112 sal_Int32 prefix = registryName.getLength();
1113 if (!registryName.endsWith("/")) {
1114 prefix += RTL_CONSTASCII_LENGTH("/");
1115 }
1116 const css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1117 keys(registry->openKeys());
1118 css::uno::Reference< css::lang::XMultiComponentFactory > smgr(
1119 context->getServiceManager(), css::uno::UNO_SET_THROW);
1120 for (css::uno::Reference< css::registry::XRegistryKey > const & key : keys) {
1121 OUString name(key->getKeyName().copy(prefix));
1122 data->implementationNames.push_back(name);
1123 css::uno::Reference< css::registry::XRegistryKey > singletons(
1124 key->openKey("UNO/SINGLETONS"));
1125 if (singletons.is()) {
1126 sal_Int32 prefix2 = key->getKeyName().getLength() +
1127 RTL_CONSTASCII_LENGTH("/UNO/SINGLETONS/");
1128 const css::uno::Sequence<
1129 css::uno::Reference< css::registry::XRegistryKey > >
1130 singletonKeys(singletons->openKeys());
1131 for (css::uno::Reference< css::registry::XRegistryKey > const & singletonKey : singletonKeys) {
1132 data->singletons.emplace_back(
1133 singletonKey->getKeyName().copy(prefix2), name);
1134 }
1135 }
1136 if (factories != nullptr) {
1137 factories->push_back(
1138 componentLoader->activate(
1139 name, OUString(), componentUrl, key));
1140 }
1141 }
1142}
1143
1144void BackendImpl::ComponentPackageImpl::getComponentInfo(
1145 ComponentBackendDb::Data * data,
1146 std::vector< css::uno::Reference< css::uno::XInterface > > * factories,
1147 Reference<XComponentContext> const & xContext )
1148{
1149 const Reference<loader::XImplementationLoader> xLoader(
1150 xContext->getServiceManager()->createInstanceWithContext(
1151 m_loader, xContext ), UNO_QUERY );
1152 if (! xLoader.is())
1153 {
1154 throw css::deployment::DeploymentException(
1155 "cannot instantiate loader " + m_loader,
1156 static_cast< OWeakObject * >(this), Any());
1157 }
1158
1159 // HACK: highly dependent on stoc/source/servicemanager
1160 // and stoc/source/implreg implementation which rely on the same
1161 // services.rdb format!
1162 // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by
1163 // writeRegistryInfo, however, but are known, fixed values here, so
1164 // can be passed into extractComponentData
1165 OUString url(getURL());
1166 const Reference<registry::XSimpleRegistry> xMemReg(
1167 xContext->getServiceManager()->createInstanceWithContext(
1168 "com.sun.star.registry.SimpleRegistry", xContext ),
1169 UNO_QUERY_THROW );
1170 xMemReg->open( OUString() /* in mem */, false, true );
1171 xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url );
1172 extractComponentData(
1173 xContext, xMemReg->getRootKey(), data, factories, xLoader, url);
1174}
1175
1176void BackendImpl::ComponentPackageImpl::componentLiveInsertion(
1177 ComponentBackendDb::Data const & data,
1178 std::vector< css::uno::Reference< css::uno::XInterface > > const &
1179 factories)
1180{
1181 css::uno::Reference< css::uno::XComponentContext > rootContext(
1182 getMyBackend()->getRootContext());
1183 css::uno::Reference< css::container::XSet > set(
1184 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1185 std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator
1186 factory(factories.begin());
1187 for (auto const& implementationName : data.implementationNames)
1188 {
1189 try {
1190 set->insert(css::uno::Any(*factory++));
1191 } catch (const container::ElementExistException &) {
1192 SAL_WARN("desktop.deployment", "implementation already registered " << implementationName);
1193 }
1194 }
1195 if (data.singletons.empty()) return;
1196
1197 css::uno::Reference< css::container::XNameContainer > cont(
1198 rootContext, css::uno::UNO_QUERY_THROW);
1199 for (auto const& singleton : data.singletons)
1200 {
1201 OUString name("/singletons/" + singleton.first);
1202 //TODO: Update should be atomic:
1203 try {
1204 cont->removeByName( name + "/arguments");
1205 } catch (const container::NoSuchElementException &) {}
1206 try {
1207 cont->insertByName( name + "/service", css::uno::Any(singleton.second));
1208 } catch (const container::ElementExistException &) {
1209 cont->replaceByName( name + "/service", css::uno::Any(singleton.second));
1210 }
1211 try {
1212 cont->insertByName(name, css::uno::Any());
1213 } catch (const container::ElementExistException &) {
1214 SAL_WARN("desktop.deployment", "singleton already registered " << singleton.first);
1215 cont->replaceByName(name, css::uno::Any());
1216 }
1217 }
1218}
1219
1220void BackendImpl::ComponentPackageImpl::componentLiveRemoval(
1221 ComponentBackendDb::Data const & data)
1222{
1223 css::uno::Reference< css::uno::XComponentContext > rootContext(
1224 getMyBackend()->getRootContext());
1225 css::uno::Reference< css::container::XSet > set(
1226 rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
1227 for (auto const& implementationName : data.implementationNames)
1228 {
1229 try {
1230 set->remove(css::uno::Any(implementationName));
1231 } catch (const css::container::NoSuchElementException &) {
1232 // ignore if factory has not been live deployed
1233 }
1234 }
1235 if (data.singletons.empty())
1236 return;
1237
1238 css::uno::Reference< css::container::XNameContainer > cont(
1239 rootContext, css::uno::UNO_QUERY_THROW);
1240 for (auto const& singleton : data.singletons)
1241 {
1242 OUString name("/singletons/" + singleton.first);
1243 //TODO: Removal should be atomic:
1244 try {
1245 cont->removeByName(name);
1246 } catch (const container::NoSuchElementException &) {}
1247 try {
1248 cont->removeByName( name + "/service" );
1249 } catch (const container::NoSuchElementException &) {}
1250 try {
1251 cont->removeByName( name + "/arguments" );
1252 } catch (const container::NoSuchElementException &) {}
1253 }
1254}
1255
1256// Package
1257
1258//We could use here BackendImpl::hasActiveEntry. However, this check is just as well.
1259//And it also shows the problem if another extension has overwritten an implementation
1260//entry, because it contains the same service implementation
1261beans::Optional< beans::Ambiguous<sal_Bool> >
1262BackendImpl::ComponentPackageImpl::isRegistered_(
1263 ::osl::ResettableMutexGuard &,
1264 ::rtl::Reference<AbortChannel> const & abortChannel,
1265 Reference<XCommandEnvironment> const & )
1266{
1267 if (m_registered == Reg::Uninit)
1268 {
1269 m_registered = Reg::NotRegistered;
1270 const Reference<registry::XSimpleRegistry> xRDB( getRDB() );
1271 if (xRDB.is())
1272 {
1273 bool bAmbiguousComponentName = false;
1274 // lookup rdb for location URL:
1275 const Reference<registry::XRegistryKey> xRootKey(
1276 xRDB->getRootKey() );
1277 const Reference<registry::XRegistryKey> xImplKey(
1278 xRootKey->openKey( "IMPLEMENTATIONS" ) );
1279 Sequence<OUString> implNames;
1280 if (xImplKey.is() && xImplKey->isValid())
1281 implNames = xImplKey->getKeyNames();
1282 OUString const * pImplNames = implNames.getConstArray();
1283 sal_Int32 pos = implNames.getLength();
1284 for ( ; pos--; )
1285 {
1286 checkAborted( abortChannel );
1287 const OUString key(
1288 pImplNames[ pos ] + "/UNO/LOCATION" );
1289 const Reference<registry::XRegistryKey> xKey(
1290 xRootKey->openKey(key) );
1291 if (xKey.is() && xKey->isValid())
1292 {
1293 const OUString location( xKey->getAsciiValue() );
1294 if (location.equalsIgnoreAsciiCase( getURL() ))
1295 {
1296 break;
1297 }
1298 else
1299 {
1300 //try to match only the file name
1301 OUString thisUrl(getURL());
1302 std::u16string_view thisFileName(thisUrl.subView(thisUrl.lastIndexOf('/')));
1303
1304 std::u16string_view locationFileName(location.subView(location.lastIndexOf('/')));
1305 if (o3tl::equalsIgnoreAsciiCase(locationFileName, thisFileName))
1306 bAmbiguousComponentName = true;
1307 }
1308 }
1309 }
1310 if (pos >= 0)
1311 m_registered = Reg::Registered;
1312 else if (bAmbiguousComponentName)
1313 m_registered = Reg::MaybeRegistered;
1314 }
1315 }
1316
1317 //Different extensions can use the same service implementations. Then the extensions
1318 //which was installed last will overwrite the one from the other extension. That is
1319 //the registry will contain the path (the location) of the library or jar of the
1320 //second extension. In this case isRegistered called for the lib of the first extension
1321 //would return "not registered". That would mean that during uninstallation
1322 //XPackage::registerPackage is not called, because it just was not registered. This is,
1323 //however, necessary for jar files. Registering and unregistering update
1324 //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc
1325 //Therefore, we will return always "is ambiguous" if the path of this component cannot
1326 //be found in the registry and if there is another path and both have the same file name (but
1327 //the rest of the path is different).
1328 //If the caller cannot precisely determine that this package was registered, then it must
1329 //call registerPackage.
1330 bool bAmbiguous = m_registered == Reg::Void // Reg::Void == we are in the progress of unregistration
1331 || m_registered == Reg::MaybeRegistered;
1332 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1333 true /* IsPresent */,
1334 beans::Ambiguous<sal_Bool>(
1335 m_registered == Reg::Registered, bAmbiguous) );
1336}
1337
1338
1339void BackendImpl::ComponentPackageImpl::processPackage_(
1340 ::osl::ResettableMutexGuard &,
1341 bool doRegisterPackage,
1342 bool startup,
1343 ::rtl::Reference<AbortChannel> const & abortChannel,
1344 Reference<XCommandEnvironment> const & xCmdEnv )
1345{
1346 BackendImpl * that = getMyBackend();
1347 OUString url(getURL());
1348 if (doRegisterPackage) {
1349 ComponentBackendDb::Data data;
1350 css::uno::Reference< css::uno::XComponentContext > context;
1351 if (startup) {
1352 context = that->getComponentContext();
1353 } else {
1354 context.set(that->getObject(url), css::uno::UNO_QUERY);
1355 if (!context.is()) {
1356 context.set(
1357 that->insertObject(
1358 url,
1359 raise_uno_process(
1360 that->getComponentContext(), abortChannel)),
1361 css::uno::UNO_QUERY_THROW);
1362 }
1363 }
1364 css::uno::Reference< css::registry::XImplementationRegistration> impreg(
1365 context->getServiceManager()->createInstanceWithContext(
1366 "com.sun.star.registry.ImplementationRegistration",
1367 context),
1368 css::uno::UNO_QUERY_THROW);
1369 css::uno::Reference< css::registry::XSimpleRegistry > rdb(getRDB());
1370 impreg->registerImplementation(m_loader, url, rdb);
1371 // Only write to unorc after successful registration; it may fail if
1372 // there is no suitable java
1373 if (m_loader == "com.sun.star.loader.Java2" && !jarManifestHeaderPresent(url, u"UNO-Type-Path", xCmdEnv))
1374 {
1375 that->addToUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1376 data.javaTypeLibrary = true;
1377 }
1378 std::vector< css::uno::Reference< css::uno::XInterface > > factories;
1379 getComponentInfo(&data, startup ? nullptr : &factories, context);
1380 if (!startup) {
1381 try {
1382 componentLiveInsertion(data, factories);
1383 } catch (css::uno::Exception &) {
1384 TOOLS_INFO_EXCEPTION("desktop.deployment", "caught");
1385 try {
1386 impreg->revokeImplementation(url, rdb);
1387 } catch (css::uno::RuntimeException &) {
1388 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignored");
1389 }
1390 throw;
1391 }
1392 }
1393 m_registered = Reg::Registered;
1394 that->addDataToDb(url, data);
1395 } else { // revoke
1396 m_registered = Reg::Void;
1397 ComponentBackendDb::Data data(that->readDataFromDb(url));
1398 css::uno::Reference< css::uno::XComponentContext > context(
1399 that->getObject(url), css::uno::UNO_QUERY);
1400 bool remoteContext = context.is();
1401 if (!remoteContext) {
1402 context = that->getComponentContext();
1403 }
1404 if (!startup) {
1405 componentLiveRemoval(data);
1406 }
1407 css::uno::Reference< css::registry::XImplementationRegistration >(
1408 context->getServiceManager()->createInstanceWithContext(
1409 "com.sun.star.registry.ImplementationRegistration",
1410 context),
1411 css::uno::UNO_QUERY_THROW)->revokeImplementation(url, getRDB());
1412 if (data.javaTypeLibrary) {
1413 that->removeFromUnoRc(RCITEM_JAR_TYPELIB, url, xCmdEnv);
1414 }
1415 if (remoteContext) {
1416 that->releaseObject(url);
1417 }
1418 m_registered = Reg::NotRegistered;
1419 getMyBackend()->revokeEntryFromDb(url);
1420 }
1421}
1422
1423BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl(
1425 OUString const & url, OUString const & name,
1426 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1427 bool jarFile, bool bRemoved, OUString const & identifier)
1428 : Package( myBackend, url, name, name /* display-name */,
1429 xPackageType, bRemoved, identifier),
1430 m_jarFile( jarFile )
1431{
1432}
1433
1434// Package
1435BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const
1436{
1437 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1438 if (nullptr == pBackend)
1439 {
1440 //May throw a DisposedException
1441 check();
1442 //We should never get here...
1443 throw RuntimeException( "Failed to get the BackendImpl",
1444 static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this)));
1445 }
1446 return pBackend;
1447}
1448
1449beans::Optional< beans::Ambiguous<sal_Bool> >
1450BackendImpl::TypelibraryPackageImpl::isRegistered_(
1451 ::osl::ResettableMutexGuard &,
1453 Reference<XCommandEnvironment> const & )
1454{
1455 BackendImpl * that = getMyBackend();
1456 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1457 true /* IsPresent */,
1458 beans::Ambiguous<sal_Bool>(
1459 that->hasInUnoRc(
1460 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, getURL() ),
1461 false /* IsAmbiguous */ ) );
1462}
1463
1464
1465void BackendImpl::TypelibraryPackageImpl::processPackage_(
1466 ::osl::ResettableMutexGuard &,
1467 bool doRegisterPackage,
1468 bool /*startup*/,
1470 Reference<XCommandEnvironment> const & xCmdEnv )
1471{
1472 BackendImpl * that = getMyBackend();
1473 const OUString url( getURL() );
1474
1475 if (doRegisterPackage)
1476 {
1477 // live insertion:
1478 if (m_jarFile) {
1479 // xxx todo add to classpath at runtime: ???
1480 //SB: It is probably not worth it to add the live inserted type
1481 // library JAR to the UnoClassLoader in the soffice process. Any
1482 // live inserted component JAR that might reference this type
1483 // library JAR runs in its own uno process, so there is probably no
1484 // Java code in the soffice process that would see any UNO types
1485 // introduced by this type library JAR.
1486 }
1487 else // RDB:
1488 {
1489 css::uno::Reference< css::container::XSet >(
1490 that->getComponentContext()->getValueByName(
1491 "/singletons"
1492 "/com.sun.star.reflection.theTypeDescriptionManager"),
1493 css::uno::UNO_QUERY_THROW)->insert(
1494 css::uno::Any(expandUnoRcUrl(url)));
1495 }
1496
1497 that->addToUnoRc( m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB,
1498 url, xCmdEnv );
1499 }
1500 else // revokePackage()
1501 {
1502 that->removeFromUnoRc(
1503 m_jarFile ? RCITEM_JAR_TYPELIB : RCITEM_RDB_TYPELIB, url, xCmdEnv );
1504
1505 // revoking types at runtime, possible, sensible?
1506 if (!m_jarFile) {
1507 css::uno::Reference< css::container::XSet >(
1508 that->getComponentContext()->getValueByName(
1509 "/singletons"
1510 "/com.sun.star.reflection.theTypeDescriptionManager"),
1511 css::uno::UNO_QUERY_THROW)->remove(
1512 css::uno::Any(expandUnoRcUrl(url)));
1513 }
1514 }
1515}
1516
1517BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl(
1519 OUString const & url, OUString const & name,
1520 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1521 bool bRemoved, OUString const & identifier, OUString platform)
1522 : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier)
1523 , m_aPlatform(std::move(platform))
1524{
1525 OSL_PRECOND(bRemoved, "this class can only be used for removing packages!");
1526}
1527
1528BackendImpl *
1529BackendImpl::OtherPlatformPackageImpl::getMyBackend() const
1530{
1531 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1532 if (nullptr == pBackend)
1533 {
1534 //Throws a DisposedException
1535 check();
1536 //We should never get here...
1537 throw RuntimeException("Failed to get the BackendImpl",
1538 static_cast<OWeakObject*>(const_cast<OtherPlatformPackageImpl*>(this)));
1539 }
1540 return pBackend;
1541}
1542
1543Reference<registry::XSimpleRegistry>
1544BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const
1545{
1546 OUString const aRDB(m_aPlatform + ".rdb");
1547 OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB));
1548
1549 Reference<registry::XSimpleRegistry> xRegistry;
1550
1551 try
1552 {
1553 xRegistry.set(
1554 impl_createInstance("com.sun.star.registry.SimpleRegistry"),
1555 UNO_QUERY)
1556 ;
1557 if (xRegistry.is())
1558 xRegistry->open(expandUnoRcUrl(aRDBPath), false, false);
1559 }
1560 catch (registry::InvalidRegistryException const&)
1561 {
1562 // If the registry does not exist, we do not need to bother at all
1563 xRegistry.set(nullptr);
1564 }
1565
1566 SAL_WARN_IF( !xRegistry.is(), "desktop.deployment", "could not create registry for the package's platform");
1567 return xRegistry;
1568}
1569
1570Reference<XInterface>
1571BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService)
1572const
1573{
1574 Reference<XComponentContext> const xContext(getMyBackend()->getComponentContext());
1575 OSL_ASSERT(xContext.is());
1576 Reference<XInterface> xService;
1577 if (xContext.is())
1578 xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext));
1579 return xService;
1580}
1581
1582beans::Optional<beans::Ambiguous<sal_Bool> >
1583BackendImpl::OtherPlatformPackageImpl::isRegistered_(
1584 ::osl::ResettableMutexGuard& /* guard */,
1585 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1586 Reference<XCommandEnvironment> const& /* xCmdEnv */ )
1587{
1588 return beans::Optional<beans::Ambiguous<sal_Bool> >(true,
1589 beans::Ambiguous<sal_Bool>(true, false));
1590}
1591
1592void
1593BackendImpl::OtherPlatformPackageImpl::processPackage_(
1594 ::osl::ResettableMutexGuard& /* guard */,
1595 bool bRegisterPackage,
1596 bool /* bStartup */,
1597 ::rtl::Reference<AbortChannel> const& /* abortChannel */,
1598 Reference<XCommandEnvironment> const& /* xCmdEnv */)
1599{
1600 OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!");
1601
1602 OUString const aURL(getURL());
1603
1604 Reference<registry::XSimpleRegistry> const xServicesRDB(impl_openRDB());
1605 Reference<registry::XImplementationRegistration> const xImplReg(
1606 impl_createInstance("com.sun.star.registry.ImplementationRegistration"),
1607 UNO_QUERY)
1608 ;
1609 if (xImplReg.is() && xServicesRDB.is())
1610 xImplReg->revokeImplementation(aURL, xServicesRDB);
1611 if (xServicesRDB.is())
1612 xServicesRDB->close();
1613
1614 getMyBackend()->revokeEntryFromDb(aURL);
1615}
1616
1617BackendImpl * BackendImpl::ComponentsPackageImpl::getMyBackend() const
1618{
1619 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
1620 if (nullptr == pBackend)
1621 {
1622 //Throws a DisposedException
1623 check();
1624 //We should never get here...
1625 throw RuntimeException("Failed to get the BackendImpl",
1626 static_cast<OWeakObject*>(const_cast<ComponentsPackageImpl *>(this)));
1627 }
1628 return pBackend;
1629}
1630
1631beans::Optional< beans::Ambiguous<sal_Bool> >
1632BackendImpl::ComponentsPackageImpl::isRegistered_(
1633 ::osl::ResettableMutexGuard &,
1635 Reference<XCommandEnvironment> const & )
1636{
1637 return beans::Optional< beans::Ambiguous<sal_Bool> >(
1638 true,
1639 beans::Ambiguous<sal_Bool>(
1640 getMyBackend()->hasInUnoRc(RCITEM_COMPONENTS, getURL()), false));
1641}
1642
1643void BackendImpl::ComponentsPackageImpl::processPackage_(
1644 ::osl::ResettableMutexGuard &,
1645 bool doRegisterPackage,
1646 bool startup,
1647 ::rtl::Reference<AbortChannel> const & abortChannel,
1648 Reference<XCommandEnvironment> const & xCmdEnv )
1649{
1650 BackendImpl * that = getMyBackend();
1651 OUString url(getURL());
1652 if (doRegisterPackage) {
1653 if (!startup) {
1654 css::uno::Reference< css::uno::XComponentContext > context(
1655 that->getObject(url), css::uno::UNO_QUERY);
1656 if (!context.is()) {
1657 context.set(
1658 that->insertObject(
1659 url,
1660 raise_uno_process(
1661 that->getComponentContext(), abortChannel)),
1662 css::uno::UNO_QUERY_THROW);
1663 }
1664 // This relies on the root component context's service manager
1665 // supporting the extended XSet semantics:
1666 css::uno::Sequence< css::beans::NamedValue > args
1667 {
1668 { "uri", css::uno::Any(expandUnoRcUrl(url)) },
1669 { "component-context", css::uno::Any(context) }
1670 };
1671 css::uno::Reference< css::container::XSet > smgr(
1672 that->getRootContext()->getServiceManager(),
1673 css::uno::UNO_QUERY_THROW);
1674 smgr->insert(css::uno::Any(args));
1675 }
1676 that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1677 } else { // revoke
1678 that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv);
1679 if (!startup) {
1680 // This relies on the root component context's service manager
1681 // supporting the extended XSet semantics:
1682 css::uno::Sequence< css::beans::NamedValue > args { { "uri", css::uno::Any(expandUnoRcUrl(url)) } };
1683 css::uno::Reference< css::container::XSet > smgr(
1684 that->getRootContext()->getServiceManager(),
1685 css::uno::UNO_QUERY_THROW);
1686 smgr->remove(css::uno::Any(args));
1687 }
1688 that->releaseObject(url);
1689 that->revokeEntryFromDb(url); // in case it got added with old code
1690 }
1691}
1692
1693BackendImpl::ComponentsPackageImpl::ComponentsPackageImpl(
1695 OUString const & url, OUString const & name,
1696 Reference<deployment::XPackageTypeInfo> const & xPackageType,
1697 bool bRemoved, OUString const & identifier)
1698 : Package( myBackend, url, name, name /* display-name */,
1699 xPackageType, bRemoved, identifier)
1700{}
1701
1702} // anon namespace
1703
1704} // namespace dp_registry
1705
1706
1707extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1709 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
1710{
1711 return cppu::acquire(new dp_registry::backend::component::BackendImpl(args, context));
1712}
1713
1714/* 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:555
float u
const char * name
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2642
#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 makeURL(std::u16string_view baseURL, OUString const &relPath_)
appends a relative path to a url.
Definition: dp_misc.cxx:253
OUString makeRcTerm(OUString const &url)
Definition: dp_misc.cxx:301
OUString expandUnoRcUrl(OUString const &url)
Definition: dp_misc.cxx:315
Reference< XInterface > resolveUnoURL(OUString const &connectString, Reference< XComponentContext > const &xLocalContext, AbortChannel const *abortChannel)
Definition: dp_misc.cxx:429
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:410
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readLine(OUString *res, std::u16string_view startingWith, ::ucbhelper::Content &ucb_content, rtl_TextEncoding textenc)
Definition: dp_ucb.cxx:200
OUString expandUnoRcTerm(OUString const &term_)
Definition: dp_misc.cxx:294
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool platform_fits(std::u16string_view platform_string)
oslProcess raiseProcess(OUString const &appURL, Sequence< OUString > const &args)
Definition: dp_misc.cxx:374
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)
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
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