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