1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <cppuhelper/implbase.hxx>
21 #include <comphelper/servicedecl.hxx>
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>
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>
45 #include <dp_dependencies.hxx>
46 #include <dp_descriptioninfoset.hxx>
47 #include <dp_identifier.hxx>
48 #include <dp_services.hxx>
49 #include <dp_version.hxx>
51 #include <dp_update.hxx>
53 namespace beans
= com::sun::star::beans
;
54 namespace deployment
= com::sun::star::deployment
;
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
;
64 class PackageInformationProvider
:
65 public ::cppu::WeakImplHelper
< deployment::XPackageInformationProvider
>
69 explicit PackageInformationProvider( uno::Reference
< uno::XComponentContext
>const& xContext
);
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
;
78 uno::Reference
< uno::XComponentContext
> mxContext
;
80 OUString
getPackageLocation( const OUString
& repository
,
81 const OUString
& _sExtensionId
);
83 uno::Reference
< deployment::XUpdateInformationProvider
> mxUpdateInformation
;
87 PackageInformationProvider::PackageInformationProvider( uno::Reference
< uno::XComponentContext
> const& xContext
) :
88 mxContext( xContext
),
89 mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext
) )
93 OUString
PackageInformationProvider::getPackageLocation(
94 const OUString
& repository
,
95 const OUString
& _rExtensionId
)
97 OUString aLocationURL
;
98 uno::Reference
<deployment::XExtensionManager
> xManager
=
99 deployment::ExtensionManager::get(mxContext
);
103 const uno::Sequence
< uno::Reference
< deployment::XPackage
> > packages(
104 xManager
->getDeployedExtensions(
106 uno::Reference
< task::XAbortChannel
>(),
107 uno::Reference
< css_ucb::XCommandEnvironment
> () ) );
109 for ( int pos
= packages
.getLength(); pos
--; )
113 const beans::Optional
< OUString
> aID
= packages
[ pos
]->getIdentifier();
114 if ( aID
.IsPresent
&& (aID
.Value
== _rExtensionId
) )
116 aLocationURL
= packages
[ pos
]->getURL();
120 catch ( uno::RuntimeException
& ) {}
129 PackageInformationProvider::getPackageLocation( const OUString
& _sExtensionId
)
131 OUString aLocationURL
= getPackageLocation( "user", _sExtensionId
);
133 if ( aLocationURL
.isEmpty() )
135 aLocationURL
= getPackageLocation( "shared", _sExtensionId
);
137 if ( aLocationURL
.isEmpty() )
139 aLocationURL
= getPackageLocation( "bundled", _sExtensionId
);
141 if ( !aLocationURL
.isEmpty() )
145 ::ucbhelper::Content
aContent( aLocationURL
, nullptr, mxContext
);
146 aLocationURL
= aContent
.getURL();
148 catch (const css::ucb::ContentCreationException
&)
150 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignoring");
156 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
157 PackageInformationProvider::isUpdateAvailable( const OUString
& _sExtensionId
)
159 uno::Sequence
< uno::Sequence
< OUString
> > aList
;
161 uno::Reference
<deployment::XExtensionManager
> extMgr
=
162 deployment::ExtensionManager::get(mxContext
);
169 std::vector
<std::pair
<uno::Reference
<deployment::XPackage
>, uno::Any
> > errors
;
170 dp_misc::UpdateInfoMap updateInfoMap
;
171 if (!_sExtensionId
.isEmpty())
173 std::vector
<uno::Reference
<deployment::XPackage
> > vecExtensions
;
174 uno::Reference
<deployment::XPackage
> extension
;
177 extension
= dp_misc::getExtensionWithHighestVersion(
178 extMgr
->getExtensionsWithSameIdentifier(
179 _sExtensionId
, _sExtensionId
, uno::Reference
<css_ucb::XCommandEnvironment
>()));
180 vecExtensions
.push_back(extension
);
182 catch (lang::IllegalArgumentException
&)
186 updateInfoMap
= dp_misc::getOnlineUpdateInfos(
187 mxContext
, extMgr
, mxUpdateInformation
, &vecExtensions
, errors
);
191 updateInfoMap
= dp_misc::getOnlineUpdateInfos(
192 mxContext
, extMgr
, mxUpdateInformation
, nullptr, errors
);
196 for (auto const& updateInfo
: updateInfoMap
)
198 dp_misc::UpdateInfo
const & info
= updateInfo
.second
;
200 OUString sOnlineVersion
;
203 // check, if there are unsatisfied dependencies and ignore this online update
204 dp_misc::DescriptionInfoset
infoset(mxContext
, info
.info
);
205 uno::Sequence
< uno::Reference
< xml::dom::XElement
> >
206 ds( dp_misc::Dependencies::check( infoset
) );
207 if ( ! ds
.hasElements() )
208 sOnlineVersion
= info
.version
;
211 OUString sVersionUser
;
212 OUString sVersionShared
;
213 OUString sVersionBundled
;
214 uno::Sequence
< uno::Reference
< deployment::XPackage
> > extensions
;
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");
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();
231 bool bSharedReadOnly
= extMgr
->isReadOnlyRepository("shared");
233 dp_misc::UPDATE_SOURCE sourceUser
= dp_misc::isUpdateUserExtension(
234 bSharedReadOnly
, sVersionUser
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
235 dp_misc::UPDATE_SOURCE sourceShared
= dp_misc::isUpdateSharedExtension(
236 bSharedReadOnly
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
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
;
250 updateVersion
= updateVersionShared
;
251 if (!updateVersion
.isEmpty())
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 );
265 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
PackageInformationProvider::getExtensionList()
267 const uno::Reference
<deployment::XExtensionManager
> mgr
=
268 deployment::ExtensionManager::get(mxContext
);
271 return uno::Sequence
< uno::Sequence
< OUString
> >();
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
> () );
278 uno::Sequence
< uno::Sequence
< OUString
> > retList
;
280 sal_Int32 cAllIds
= allExt
.getLength();
281 retList
.realloc(cAllIds
);
283 for (sal_Int32 i
= 0; i
< cAllIds
; i
++)
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
++)
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
] );
298 OUString aNewEntry
[2];
299 aNewEntry
[0] = dp_misc::getIdentifier(xExtension
);
300 aNewEntry
[1] = xExtension
->getVersion();
301 retList
[i
] = ::uno::Sequence
< OUString
>( aNewEntry
, 2 );
310 namespace sdecl
= comphelper::service_decl
;
311 sdecl::class_
<PackageInformationProvider
> const servicePIP
;
312 sdecl::ServiceDecl
const serviceDecl(
315 "com.sun.star.comp.deployment.PackageInformationProvider",
316 "com.sun.star.comp.deployment.PackageInformationProvider" );
318 } // namespace dp_info
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */