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