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 <cppuhelper/supportsservice.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/task/XAbortChannel.hpp>
31 #include <com/sun/star/ucb/ContentCreationException.hpp>
32 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
34 #include <com/sun/star/xml/dom/XElement.hpp>
36 #include <com/sun/star/uno/Reference.hxx>
37 #include <osl/diagnose.h>
38 #include <rtl/ustring.hxx>
39 #include <comphelper/diagnose_ex.hxx>
40 #include <ucbhelper/content.hxx>
42 #include <dp_dependencies.hxx>
43 #include <dp_descriptioninfoset.hxx>
44 #include <dp_identifier.hxx>
45 #include <dp_version.hxx>
46 #include <dp_update.hxx>
48 namespace beans
= css::beans
;
49 namespace deployment
= css::deployment
;
50 namespace lang
= css::lang
;
51 namespace task
= css::task
;
52 namespace css_ucb
= css::ucb
;
53 namespace uno
= css::uno
;
54 namespace xml
= css::xml
;
61 class PackageInformationProvider
:
62 public ::cppu::WeakImplHelper
< deployment::XPackageInformationProvider
, lang::XServiceInfo
>
66 explicit PackageInformationProvider( uno::Reference
< uno::XComponentContext
>const& xContext
);
69 virtual OUString SAL_CALL
getImplementationName() override
;
70 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
71 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
73 // XPackageInformationProvider
74 virtual OUString SAL_CALL
getPackageLocation( const OUString
& extensionId
) override
;
75 virtual uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
isUpdateAvailable( const OUString
& extensionId
) override
;
76 virtual uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
getExtensionList() override
;
80 uno::Reference
< uno::XComponentContext
> mxContext
;
82 OUString
getPackageLocation( const OUString
& repository
,
83 std::u16string_view _sExtensionId
);
85 uno::Reference
< deployment::XUpdateInformationProvider
> mxUpdateInformation
;
90 PackageInformationProvider::PackageInformationProvider( uno::Reference
< uno::XComponentContext
> const& xContext
) :
91 mxContext( xContext
),
92 mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext
) )
97 OUString
PackageInformationProvider::getImplementationName()
99 return u
"com.sun.star.comp.deployment.PackageInformationProvider"_ustr
;
102 sal_Bool
PackageInformationProvider::supportsService( const OUString
& ServiceName
)
104 return cppu::supportsService(this, ServiceName
);
107 css::uno::Sequence
< OUString
> PackageInformationProvider::getSupportedServiceNames()
110 return { u
"com.sun.star.comp.deployment.PackageInformationProvider"_ustr
};
113 OUString
PackageInformationProvider::getPackageLocation(
114 const OUString
& repository
,
115 std::u16string_view _rExtensionId
)
117 OUString aLocationURL
;
118 uno::Reference
<deployment::XExtensionManager
> xManager
=
119 deployment::ExtensionManager::get(mxContext
);
123 const uno::Sequence
< uno::Reference
< deployment::XPackage
> > packages(
124 xManager
->getDeployedExtensions(
126 uno::Reference
< task::XAbortChannel
>(),
127 uno::Reference
< css_ucb::XCommandEnvironment
> () ) );
129 for ( int pos
= packages
.getLength(); pos
--; )
133 const beans::Optional
< OUString
> aID
= packages
[ pos
]->getIdentifier();
134 if ( aID
.IsPresent
&& (aID
.Value
== _rExtensionId
) )
136 aLocationURL
= packages
[ pos
]->getURL();
140 catch ( uno::RuntimeException
& ) {}
149 PackageInformationProvider::getPackageLocation( const OUString
& _sExtensionId
)
151 OUString aLocationURL
= getPackageLocation( u
"user"_ustr
, _sExtensionId
);
153 if ( aLocationURL
.isEmpty() )
155 aLocationURL
= getPackageLocation( u
"shared"_ustr
, _sExtensionId
);
157 if ( aLocationURL
.isEmpty() )
159 aLocationURL
= getPackageLocation( u
"bundled"_ustr
, _sExtensionId
);
161 if ( !aLocationURL
.isEmpty() )
165 ::ucbhelper::Content
aContent( aLocationURL
, nullptr, mxContext
);
166 aLocationURL
= aContent
.getURL();
168 catch (const css::ucb::ContentCreationException
&)
170 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignoring");
176 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
177 PackageInformationProvider::isUpdateAvailable( const OUString
& _sExtensionId
)
179 uno::Sequence
< uno::Sequence
< OUString
> > aList
;
181 uno::Reference
<deployment::XExtensionManager
> extMgr
=
182 deployment::ExtensionManager::get(mxContext
);
189 std::vector
<std::pair
<uno::Reference
<deployment::XPackage
>, uno::Any
> > errors
;
190 dp_misc::UpdateInfoMap updateInfoMap
;
191 if (!_sExtensionId
.isEmpty())
193 std::vector
<uno::Reference
<deployment::XPackage
> > vecExtensions
;
194 uno::Reference
<deployment::XPackage
> extension
;
197 extension
= dp_misc::getExtensionWithHighestVersion(
198 extMgr
->getExtensionsWithSameIdentifier(
199 _sExtensionId
, _sExtensionId
, uno::Reference
<css_ucb::XCommandEnvironment
>()));
200 vecExtensions
.push_back(extension
);
202 catch (lang::IllegalArgumentException
&)
206 updateInfoMap
= dp_misc::getOnlineUpdateInfos(
207 mxContext
, extMgr
, mxUpdateInformation
, &vecExtensions
, errors
);
211 updateInfoMap
= dp_misc::getOnlineUpdateInfos(
212 mxContext
, extMgr
, mxUpdateInformation
, nullptr, errors
);
216 for (auto const& updateInfo
: updateInfoMap
)
218 dp_misc::UpdateInfo
const & info
= updateInfo
.second
;
220 OUString sOnlineVersion
;
223 // check, if there are unsatisfied dependencies and ignore this online update
224 dp_misc::DescriptionInfoset
infoset(mxContext
, info
.info
);
225 uno::Sequence
< uno::Reference
< xml::dom::XElement
> >
226 ds( dp_misc::Dependencies::check( infoset
) );
227 if ( ! ds
.hasElements() )
228 sOnlineVersion
= info
.version
;
231 OUString sVersionUser
;
232 OUString sVersionShared
;
233 OUString sVersionBundled
;
234 uno::Sequence
< uno::Reference
< deployment::XPackage
> > extensions
;
236 extensions
= extMgr
->getExtensionsWithSameIdentifier(
237 dp_misc::getIdentifier(info
.extension
), info
.extension
->getName(),
238 uno::Reference
<css_ucb::XCommandEnvironment
>());
239 } catch (const lang::IllegalArgumentException
&) {
240 TOOLS_WARN_EXCEPTION("desktop.deployment", "ignoring");
243 OSL_ASSERT(extensions
.getLength() == 3);
244 if (extensions
[0].is() )
245 sVersionUser
= extensions
[0]->getVersion();
246 if (extensions
[1].is() )
247 sVersionShared
= extensions
[1]->getVersion();
248 if (extensions
[2].is() )
249 sVersionBundled
= extensions
[2]->getVersion();
251 bool bSharedReadOnly
= extMgr
->isReadOnlyRepository(u
"shared"_ustr
);
253 dp_misc::UPDATE_SOURCE sourceUser
= dp_misc::isUpdateUserExtension(
254 bSharedReadOnly
, sVersionUser
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
255 dp_misc::UPDATE_SOURCE sourceShared
= dp_misc::isUpdateSharedExtension(
256 bSharedReadOnly
, sVersionShared
, sVersionBundled
, sOnlineVersion
);
258 OUString updateVersionUser
;
259 OUString updateVersionShared
;
260 if (sourceUser
!= dp_misc::UPDATE_SOURCE_NONE
)
261 updateVersionUser
= dp_misc::getHighestVersion(
262 sVersionShared
, sVersionBundled
, sOnlineVersion
);
263 if (sourceShared
!= dp_misc::UPDATE_SOURCE_NONE
)
264 updateVersionShared
= dp_misc::getHighestVersion(
265 OUString(), sVersionBundled
, sOnlineVersion
);
266 OUString updateVersion
;
267 if (dp_misc::compareVersions(updateVersionUser
, updateVersionShared
) == dp_misc::GREATER
)
268 updateVersion
= updateVersionUser
;
270 updateVersion
= updateVersionShared
;
271 if (!updateVersion
.isEmpty())
274 OUString aNewEntry
[2];
275 aNewEntry
[0] = updateInfo
.first
;
276 aNewEntry
[1] = updateVersion
;
277 aList
.realloc( ++nCount
);
278 aList
.getArray()[ nCount
-1 ] = ::uno::Sequence
< OUString
>( aNewEntry
, 2 );
285 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
PackageInformationProvider::getExtensionList()
287 const uno::Reference
<deployment::XExtensionManager
> mgr
=
288 deployment::ExtensionManager::get(mxContext
);
291 return uno::Sequence
< uno::Sequence
< OUString
> >();
293 const uno::Sequence
< uno::Sequence
< uno::Reference
<deployment::XPackage
> > >
294 allExt
= mgr
->getAllExtensions(
295 uno::Reference
< task::XAbortChannel
>(),
296 uno::Reference
< css_ucb::XCommandEnvironment
> () );
298 uno::Sequence
< uno::Sequence
< OUString
> > retList
;
300 sal_Int32 cAllIds
= allExt
.getLength();
301 retList
.realloc(cAllIds
);
302 auto pretList
= retList
.getArray();
304 for (sal_Int32 i
= 0; i
< cAllIds
; i
++)
306 //The inner sequence contains extensions with the same identifier from
307 //all the different repositories, that is user, share, bundled.
308 const uno::Sequence
< uno::Reference
< deployment::XPackage
> > &
309 seqExtension
= allExt
[i
];
310 sal_Int32 cExt
= seqExtension
.getLength();
311 OSL_ASSERT(cExt
== 3);
312 for (sal_Int32 j
= 0; j
< cExt
; j
++)
314 //ToDo according to the old code the first found extension is used
315 //even if another one with the same id has a better version.
316 uno::Reference
< deployment::XPackage
> const & xExtension( seqExtension
[j
] );
319 pretList
[i
] = { dp_misc::getIdentifier(xExtension
), xExtension
->getVersion() };
328 } // namespace dp_info
330 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
331 com_sun_star_comp_deployment_PackageInformationProvider_get_implementation(
332 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
334 return cppu::acquire(new dp_info::PackageInformationProvider(context
));
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */