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