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