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