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