LibreOffice Module desktop (master)  1
dp_informationprovider.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 #include <cppuhelper/implbase.hxx>
22 
23 #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
24 #include <com/sun/star/deployment/XPackage.hpp>
25 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
26 #include <com/sun/star/deployment/ExtensionManager.hpp>
27 #include <com/sun/star/deployment/XUpdateInformationProvider.hpp>
28 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/registry/XRegistryKey.hpp>
31 #include <com/sun/star/task/XAbortChannel.hpp>
32 #include <com/sun/star/ucb/ContentCreationException.hpp>
33 #include <com/sun/star/uno/XComponentContext.hpp>
34 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
35 #include <com/sun/star/xml/dom/XElement.hpp>
36 #include <com/sun/star/xml/dom/XNode.hpp>
37 
38 #include <com/sun/star/uno/Reference.hxx>
39 #include <osl/diagnose.h>
40 #include <sal/log.hxx>
41 #include <rtl/ustring.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <ucbhelper/content.hxx>
44 
45 #include <dp_dependencies.hxx>
47 #include <dp_identifier.hxx>
48 #include <dp_services.hxx>
49 #include <dp_version.hxx>
50 #include <dp_misc.h>
51 #include <dp_update.hxx>
52 
53 namespace beans = com::sun::star::beans ;
55 namespace lang = com::sun::star::lang ;
56 namespace task = com::sun::star::task ;
57 namespace css_ucb = com::sun::star::ucb ;
58 namespace uno = com::sun::star::uno ;
59 namespace xml = com::sun::star::xml ;
60 
61 
62 namespace dp_info {
63 
65  public ::cppu::WeakImplHelper< deployment::XPackageInformationProvider >
66 
67 {
68  public:
69  explicit PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext);
70 
71  // XPackageInformationProvider
72  virtual OUString SAL_CALL getPackageLocation( const OUString& extensionId ) override;
73  virtual uno::Sequence< uno::Sequence< OUString > > SAL_CALL isUpdateAvailable( const OUString& extensionId ) override;
74  virtual uno::Sequence< uno::Sequence< OUString > > SAL_CALL getExtensionList() override;
75 
76 private:
77 
78  uno::Reference< uno::XComponentContext> mxContext;
79 
80  OUString getPackageLocation( const OUString& repository,
81  const OUString& _sExtensionId );
82 
83  uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation;
84 };
85 
86 
87 PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) :
88  mxContext( xContext ),
89  mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) )
90 {
91 }
92 
94  const OUString & repository,
95  const OUString& _rExtensionId )
96 {
97  OUString aLocationURL;
98  uno::Reference<deployment::XExtensionManager> xManager =
99  deployment::ExtensionManager::get(mxContext);
100 
101  if ( xManager.is() )
102  {
103  const uno::Sequence< uno::Reference< deployment::XPackage > > packages(
104  xManager->getDeployedExtensions(
105  repository,
106  uno::Reference< task::XAbortChannel >(),
107  uno::Reference< css_ucb::XCommandEnvironment > () ) );
108 
109  for ( int pos = packages.getLength(); pos--; )
110  {
111  try
112  {
113  const beans::Optional< OUString > aID = packages[ pos ]->getIdentifier();
114  if ( aID.IsPresent && (aID.Value == _rExtensionId ) )
115  {
116  aLocationURL = packages[ pos ]->getURL();
117  break;
118  }
119  }
120  catch ( uno::RuntimeException & ) {}
121  }
122  }
123 
124  return aLocationURL;
125 }
126 
127 
128 OUString SAL_CALL
129 PackageInformationProvider::getPackageLocation( const OUString& _sExtensionId )
130 {
131  OUString aLocationURL = getPackageLocation( "user", _sExtensionId );
132 
133  if ( aLocationURL.isEmpty() )
134  {
135  aLocationURL = getPackageLocation( "shared", _sExtensionId );
136  }
137  if ( aLocationURL.isEmpty() )
138  {
139  aLocationURL = getPackageLocation( "bundled", _sExtensionId );
140  }
141  if ( !aLocationURL.isEmpty() )
142  {
143  try
144  {
145  ::ucbhelper::Content aContent( aLocationURL, nullptr, mxContext );
146  aLocationURL = aContent.getURL();
147  }
148  catch (const css::ucb::ContentCreationException&)
149  {
150  TOOLS_WARN_EXCEPTION("desktop.deployment", "ignoring");
151  }
152  }
153  return aLocationURL;
154 }
155 
156 uno::Sequence< uno::Sequence< OUString > > SAL_CALL
157 PackageInformationProvider::isUpdateAvailable( const OUString& _sExtensionId )
158 {
159  uno::Sequence< uno::Sequence< OUString > > aList;
160 
161  uno::Reference<deployment::XExtensionManager> extMgr =
162  deployment::ExtensionManager::get(mxContext);
163 
164  if (!extMgr.is())
165  {
166  OSL_ASSERT(false);
167  return aList;
168  }
169  std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors;
170  dp_misc::UpdateInfoMap updateInfoMap;
171  if (!_sExtensionId.isEmpty())
172  {
173  std::vector<uno::Reference<deployment::XPackage> > vecExtensions;
174  uno::Reference<deployment::XPackage> extension;
175  try
176  {
178  extMgr->getExtensionsWithSameIdentifier(
179  _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>()));
180  vecExtensions.push_back(extension);
181  }
182  catch (lang::IllegalArgumentException &)
183  {
184  OSL_ASSERT(false);
185  }
186  updateInfoMap = dp_misc::getOnlineUpdateInfos(
187  mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors);
188  }
189  else
190  {
191  updateInfoMap = dp_misc::getOnlineUpdateInfos(
192  mxContext, extMgr, mxUpdateInformation, nullptr, errors);
193  }
194 
195  int nCount = 0;
196  for (auto const& updateInfo : updateInfoMap)
197  {
198  dp_misc::UpdateInfo const & info = updateInfo.second;
199 
200  OUString sOnlineVersion;
201  if (info.info.is())
202  {
203  // check, if there are unsatisfied dependencies and ignore this online update
205  uno::Sequence< uno::Reference< xml::dom::XElement > >
206  ds( dp_misc::Dependencies::check( infoset ) );
207  if ( ! ds.hasElements() )
208  sOnlineVersion = info.version;
209  }
210 
211  OUString sVersionUser;
212  OUString sVersionShared;
213  OUString sVersionBundled;
214  uno::Sequence< uno::Reference< deployment::XPackage> > extensions;
215  try {
216  extensions = extMgr->getExtensionsWithSameIdentifier(
217  dp_misc::getIdentifier(info.extension), info.extension->getName(),
218  uno::Reference<css_ucb::XCommandEnvironment>());
219  } catch (const lang::IllegalArgumentException&) {
220  TOOLS_WARN_EXCEPTION("desktop.deployment", "ignoring");
221  continue;
222  }
223  OSL_ASSERT(extensions.getLength() == 3);
224  if (extensions[0].is() )
225  sVersionUser = extensions[0]->getVersion();
226  if (extensions[1].is() )
227  sVersionShared = extensions[1]->getVersion();
228  if (extensions[2].is() )
229  sVersionBundled = extensions[2]->getVersion();
230 
231  bool bSharedReadOnly = extMgr->isReadOnlyRepository("shared");
232 
234  bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion);
236  bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion);
237 
238  OUString updateVersionUser;
239  OUString updateVersionShared;
240  if (sourceUser != dp_misc::UPDATE_SOURCE_NONE)
241  updateVersionUser = dp_misc::getHighestVersion(
242  sVersionShared, sVersionBundled, sOnlineVersion);
243  if (sourceShared != dp_misc::UPDATE_SOURCE_NONE)
244  updateVersionShared = dp_misc::getHighestVersion(
245  OUString(), sVersionBundled, sOnlineVersion);
246  OUString updateVersion;
247  if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER)
248  updateVersion = updateVersionUser;
249  else
250  updateVersion = updateVersionShared;
251  if (!updateVersion.isEmpty())
252  {
253 
254  OUString aNewEntry[2];
255  aNewEntry[0] = updateInfo.first;
256  aNewEntry[1] = updateVersion;
257  aList.realloc( ++nCount );
258  aList[ nCount-1 ] = ::uno::Sequence< OUString >( aNewEntry, 2 );
259  }
260  }
261  return aList;
262 }
263 
264 
265 uno::Sequence< uno::Sequence< OUString > > SAL_CALL PackageInformationProvider::getExtensionList()
266 {
267  const uno::Reference<deployment::XExtensionManager> mgr =
268  deployment::ExtensionManager::get(mxContext);
269 
270  if (!mgr.is())
271  return uno::Sequence< uno::Sequence< OUString > >();
272 
273  const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > >
274  allExt = mgr->getAllExtensions(
275  uno::Reference< task::XAbortChannel >(),
276  uno::Reference< css_ucb::XCommandEnvironment > () );
277 
278  uno::Sequence< uno::Sequence< OUString > > retList;
279 
280  sal_Int32 cAllIds = allExt.getLength();
281  retList.realloc(cAllIds);
282 
283  for (sal_Int32 i = 0; i < cAllIds; i++)
284  {
285  //The inner sequence contains extensions with the same identifier from
286  //all the different repositories, that is user, share, bundled.
287  const uno::Sequence< uno::Reference< deployment::XPackage > > &
288  seqExtension = allExt[i];
289  sal_Int32 cExt = seqExtension.getLength();
290  OSL_ASSERT(cExt == 3);
291  for (sal_Int32 j = 0; j < cExt; j++)
292  {
293  //ToDo according to the old code the first found extension is used
294  //even if another one with the same id has a better version.
295  uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] );
296  if (xExtension.is())
297  {
298  OUString aNewEntry[2];
299  aNewEntry[0] = dp_misc::getIdentifier(xExtension);
300  aNewEntry[1] = xExtension->getVersion();
301  retList[i] = ::uno::Sequence< OUString >( aNewEntry, 2 );
302  break;
303  }
304  }
305  }
306  return retList;
307 }
308 
309 
310 namespace sdecl = comphelper::service_decl;
313  servicePIP,
314  // a private one:
315  "com.sun.star.comp.deployment.PackageInformationProvider",
316  "com.sun.star.comp.deployment.PackageInformationProvider" );
317 
318 } // namespace dp_info
319 
320 
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::map< OUString, UpdateInfo > UpdateInfoMap
Definition: dp_update.hxx:102
comphelper::service_decl::ServiceDecl const serviceDecl
Definition: dp_services.hxx:22
uno::Reference< uno::XComponentContext > mxContext
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(OUString const &version1, OUString const &version2)
Definition: dp_version.cxx:42
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
virtual uno::Sequence< uno::Sequence< OUString > > SAL_CALL getExtensionList() override
#define TOOLS_WARN_EXCEPTION(area, stream)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateSharedExtension(bool bReadOnlyShared, OUString const &sharedVersion, OUString const &bundledVersion, OUString const &onlineVersion)
Definition: dp_update.cxx:284
uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation
int i
PackageInformationProvider(uno::Reference< uno::XComponentContext >const &xContext)
sdecl::class_< PackageInformationProvider > const servicePIP
css::uno::Reference< css::xml::dom::XNode > info
Definition: dp_update.hxx:99
const OUString & getURL() const
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateUserExtension(bool bReadOnlyShared, OUString const &userVersion, OUString const &sharedVersion, OUString const &bundledVersion, OUString const &onlineVersion)
Definition: dp_update.cxx:234
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:1858
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UpdateInfoMap getOnlineUpdateInfos(css::uno::Reference< css::uno::XComponentContext > const &xContext, css::uno::Reference< css::deployment::XExtensionManager > const &xExtMgr, css::uno::Reference< css::deployment::XUpdateInformationProvider > const &updateInformation, std::vector< css::uno::Reference< css::deployment::XPackage > > const *extensionList, std::vector< std::pair< css::uno::Reference< css::deployment::XPackage >, css::uno::Any > > &out_errors)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
Check for unsatisfied dependencies.
virtual OUString SAL_CALL getPackageLocation(const OUString &extensionId) override
css::uno::Reference< css::deployment::XPackage > extension
Definition: dp_update.hxx:96
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getHighestVersion(OUString const &sharedVersion, OUString const &bundledVersion, OUString const &onlineVersion)
Definition: dp_update.cxx:390
virtual uno::Sequence< uno::Sequence< OUString > > SAL_CALL isUpdateAvailable(const OUString &extensionId) override
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
Access to the content of an XML description element.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Reference< css::deployment::XPackage > getExtensionWithHighestVersion(css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > const &seqExtensionsWithSameId)