Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "dp_update.hxx"
30 : : #include "dp_version.hxx"
31 : : #include "dp_identifier.hxx"
32 : : #include "dp_descriptioninfoset.hxx"
33 : :
34 : : #include "rtl/bootstrap.hxx"
35 : :
36 : : using namespace ::com::sun::star;
37 : : using namespace ::com::sun::star::uno;
38 : : using ::rtl::OUString;
39 : : using ::rtl::OString;
40 : :
41 : :
42 : : namespace dp_misc {
43 : : namespace {
44 : :
45 : 0 : int determineHighestVersion(
46 : : ::rtl::OUString const & userVersion,
47 : : ::rtl::OUString const & sharedVersion,
48 : : ::rtl::OUString const & bundledVersion,
49 : : ::rtl::OUString const & onlineVersion)
50 : : {
51 : 0 : int index = 0;
52 : 0 : OUString greatest = userVersion;
53 [ # # ][ # # ]: 0 : if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER)
54 : : {
55 : 0 : index = 1;
56 : 0 : greatest = sharedVersion;
57 : : }
58 [ # # ][ # # ]: 0 : if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER)
59 : : {
60 : 0 : index = 2;
61 : 0 : greatest = bundledVersion;
62 : : }
63 [ # # ][ # # ]: 0 : if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER)
64 : : {
65 : 0 : index = 3;
66 : : }
67 : 0 : return index;
68 : : }
69 : :
70 : : Sequence< Reference< xml::dom::XElement > >
71 : 0 : getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation,
72 : : Sequence< OUString > const & urls,
73 : : OUString const & identifier,
74 : : uno::Any & out_error)
75 : : {
76 : : try {
77 [ # # ][ # # ]: 0 : return updateInformation->getUpdateInformation(urls, identifier);
78 : 0 : } catch (const uno::RuntimeException &) {
79 : 0 : throw;
80 : 0 : } catch (const ucb::CommandFailedException & e) {
81 : 0 : out_error = e.Reason;
82 : 0 : } catch (const ucb::CommandAbortedException &) {
83 [ # # # # : 0 : } catch (const uno::Exception & e) {
# ]
84 [ # # ]: 0 : out_error = uno::makeAny(e);
85 : : }
86 : : return
87 : 0 : Sequence<Reference< xml::dom::XElement > >();
88 : : }
89 : :
90 : 0 : void getOwnUpdateInfos(
91 : : Reference<uno::XComponentContext> const & xContext,
92 : : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
93 : : UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors,
94 : : bool & out_allFound)
95 : : {
96 : 0 : bool allHaveOwnUpdateInformation = true;
97 [ # # ]: 0 : for (UpdateInfoMap::iterator i = inout_map.begin(); i != inout_map.end(); ++i)
98 : : {
99 : : OSL_ASSERT(i->second.extension.is());
100 [ # # ][ # # ]: 0 : Sequence<OUString> urls(i->second.extension->getUpdateInformationURLs());
101 [ # # ]: 0 : if (urls.getLength())
102 : : {
103 [ # # ]: 0 : const OUString id = dp_misc::getIdentifier(i->second.extension);
104 : 0 : uno::Any anyError;
105 : : //It is unclear from the idl if there can be a null reference returned.
106 : : //However all valid information should be the same
107 : : Sequence<Reference< xml::dom::XElement > >
108 [ # # ]: 0 : infos(getUpdateInformation(updateInformation, urls, id, anyError));
109 [ # # ]: 0 : if (anyError.hasValue())
110 [ # # ][ # # ]: 0 : out_errors.push_back(std::make_pair(i->second.extension, anyError));
[ # # ]
111 : :
112 [ # # ]: 0 : for (sal_Int32 j = 0; j < infos.getLength(); ++j)
113 : : {
114 : : dp_misc::DescriptionInfoset infoset(
115 : : xContext,
116 [ # # ][ # # ]: 0 : Reference< xml::dom::XNode >(infos[j], UNO_QUERY_THROW));
[ # # ]
117 [ # # ][ # # ]: 0 : if (!infoset.hasDescription())
118 : 0 : continue;
119 [ # # ]: 0 : boost::optional< OUString > id2(infoset.getIdentifier());
120 [ # # ][ # # ]: 0 : if (!id2)
121 : 0 : continue;
122 : : OSL_ASSERT(*id2 == id);
123 [ # # ][ # # ]: 0 : if (*id2 == id)
124 : : {
125 [ # # ]: 0 : i->second.version = infoset.getVersion();
126 : 0 : i->second.info = Reference< xml::dom::XNode >(
127 [ # # # # ]: 0 : infos[j], UNO_QUERY_THROW);
[ # # ]
128 : : }
129 [ # # ]: 0 : break;
130 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
131 : : }
132 : : else
133 : : {
134 : 0 : allHaveOwnUpdateInformation &= false;
135 : : }
136 [ # # ]: 0 : }
137 : 0 : out_allFound = allHaveOwnUpdateInformation;
138 : 0 : }
139 : :
140 : 0 : void getDefaultUpdateInfos(
141 : : Reference<uno::XComponentContext> const & xContext,
142 : : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
143 : : UpdateInfoMap& inout_map,
144 : : std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors)
145 : : {
146 [ # # ]: 0 : const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL());
147 : : OSL_ASSERT(!sDefaultURL.isEmpty());
148 : :
149 : 0 : Any anyError;
150 : : Sequence< Reference< xml::dom::XElement > >
151 : : infos(
152 : : getUpdateInformation(
153 : : updateInformation,
154 [ # # ][ # # ]: 0 : Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError));
[ # # ]
155 [ # # ]: 0 : if (anyError.hasValue())
156 [ # # ][ # # ]: 0 : out_errors.push_back(std::make_pair(Reference<deployment::XPackage>(), anyError));
[ # # ]
157 [ # # ]: 0 : for (sal_Int32 i = 0; i < infos.getLength(); ++i)
158 : : {
159 [ # # ][ # # ]: 0 : Reference< xml::dom::XNode > node(infos[i], UNO_QUERY_THROW);
160 [ # # ]: 0 : dp_misc::DescriptionInfoset infoset(xContext, node);
161 [ # # ]: 0 : boost::optional< OUString > id(infoset.getIdentifier());
162 [ # # ][ # # ]: 0 : if (!id) {
163 : 0 : continue;
164 : : }
165 [ # # ][ # # ]: 0 : UpdateInfoMap::iterator j = inout_map.find(*id);
166 [ # # ]: 0 : if (j != inout_map.end())
167 : : {
168 : : //skip those extension which provide its own update urls
169 [ # # ][ # # ]: 0 : if (j->second.extension->getUpdateInformationURLs().getLength())
[ # # ][ # # ]
170 : 0 : continue;
171 [ # # ]: 0 : OUString v(infoset.getVersion());
172 : : //look for the highest version in the online repository
173 [ # # ][ # # ]: 0 : if (dp_misc::compareVersions(v, j->second.version) ==
174 : : dp_misc::GREATER)
175 : : {
176 : 0 : j->second.version = v;
177 [ # # ]: 0 : j->second.info = node;
178 : 0 : }
179 : : }
180 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
181 : 0 : }
182 : :
183 : 0 : bool containsBundledOnly(Sequence<Reference<deployment::XPackage> > const & sameIdExtensions)
184 : : {
185 : : OSL_ASSERT(sameIdExtensions.getLength() == 3);
186 [ # # ][ # # ]: 0 : return !sameIdExtensions[0].is() && !sameIdExtensions[1].is() && sameIdExtensions[2].is();
[ # # ]
187 : : }
188 : :
189 : : /** Returns true if the list of extensions are bundled extensions and there are no
190 : : other extensions with the same identifier in the shared or user repository.
191 : : If extensionList is NULL, then it is checked if there are only bundled extensions.
192 : : */
193 : 0 : bool onlyBundledExtensions(
194 : : Reference<deployment::XExtensionManager> const & xExtMgr,
195 : : std::vector< Reference<deployment::XPackage > > const * extensionList)
196 : : {
197 : : OSL_ASSERT(xExtMgr.is());
198 : 0 : bool onlyBundled = true;
199 [ # # ]: 0 : if (extensionList)
200 : : {
201 : : typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT;
202 [ # # ][ # # ]: 0 : for (CIT i(extensionList->begin()), aEnd(extensionList->end()); onlyBundled && i != aEnd; ++i)
[ # # ][ # # ]
203 : : {
204 [ # # ]: 0 : Sequence<Reference<deployment::XPackage> > seqExt = xExtMgr->getExtensionsWithSameIdentifier(
205 [ # # ][ # # ]: 0 : dp_misc::getIdentifier(*i), (*i)->getName(), Reference<ucb::XCommandEnvironment>());
[ # # ][ # # ]
206 : :
207 [ # # ]: 0 : onlyBundled = containsBundledOnly(seqExt);
208 [ # # ]: 0 : }
209 : : }
210 : : else
211 : : {
212 : : const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt =
213 [ # # ][ # # ]: 0 : xExtMgr->getAllExtensions(Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
214 : :
215 [ # # ][ # # ]: 0 : for (int pos(0), nLen(seqAllExt.getLength()); onlyBundled && pos != nLen; ++pos)
[ # # ]
216 : : {
217 [ # # ]: 0 : onlyBundled = containsBundledOnly(seqAllExt[pos]);
218 [ # # ]: 0 : }
219 : : }
220 : 0 : return onlyBundled;
221 : : }
222 : :
223 : : } // anon namespace
224 : :
225 : :
226 : 0 : OUString getExtensionDefaultUpdateURL()
227 : : {
228 : : ::rtl::OUString sUrl(
229 : : RTL_CONSTASCII_USTRINGPARAM(
230 : : "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version")
231 : 0 : ":Version:ExtensionUpdateURL}"));
232 : 0 : ::rtl::Bootstrap::expandMacros(sUrl);
233 : 0 : return sUrl;
234 : : }
235 : :
236 : : /* returns the index of the greatest version, starting with 0
237 : :
238 : : */
239 : 0 : UPDATE_SOURCE isUpdateUserExtension(
240 : : bool bReadOnlyShared,
241 : : ::rtl::OUString const & userVersion,
242 : : ::rtl::OUString const & sharedVersion,
243 : : ::rtl::OUString const & bundledVersion,
244 : : ::rtl::OUString const & onlineVersion)
245 : : {
246 : 0 : UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
247 [ # # ]: 0 : if (bReadOnlyShared)
248 : : {
249 [ # # ]: 0 : if (!userVersion.isEmpty())
250 : : {
251 : : int index = determineHighestVersion(
252 : 0 : userVersion, sharedVersion, bundledVersion, onlineVersion);
253 [ # # ]: 0 : if (index == 1)
254 : 0 : retVal = UPDATE_SOURCE_SHARED;
255 [ # # ]: 0 : else if (index == 2)
256 : 0 : retVal = UPDATE_SOURCE_BUNDLED;
257 [ # # ]: 0 : else if (index == 3)
258 : 0 : retVal = UPDATE_SOURCE_ONLINE;
259 : : }
260 [ # # ]: 0 : else if (!sharedVersion.isEmpty())
261 : : {
262 : : int index = determineHighestVersion(
263 [ # # ]: 0 : OUString(), sharedVersion, bundledVersion, onlineVersion);
264 [ # # ]: 0 : if (index == 2)
265 : 0 : retVal = UPDATE_SOURCE_BUNDLED;
266 [ # # ]: 0 : else if (index == 3)
267 : 0 : retVal = UPDATE_SOURCE_ONLINE;
268 : :
269 : : }
270 : : }
271 : : else
272 : : {
273 [ # # ]: 0 : if (!userVersion.isEmpty())
274 : : {
275 : : int index = determineHighestVersion(
276 : 0 : userVersion, sharedVersion, bundledVersion, onlineVersion);
277 [ # # ]: 0 : if (index == 1)
278 : 0 : retVal = UPDATE_SOURCE_SHARED;
279 [ # # ]: 0 : else if (index == 2)
280 : 0 : retVal = UPDATE_SOURCE_BUNDLED;
281 [ # # ]: 0 : else if (index == 3)
282 : 0 : retVal = UPDATE_SOURCE_ONLINE;
283 : : }
284 : : }
285 : :
286 : 0 : return retVal;
287 : : }
288 : :
289 : 0 : UPDATE_SOURCE isUpdateSharedExtension(
290 : : bool bReadOnlyShared,
291 : : ::rtl::OUString const & sharedVersion,
292 : : ::rtl::OUString const & bundledVersion,
293 : : ::rtl::OUString const & onlineVersion)
294 : : {
295 [ # # ]: 0 : if (bReadOnlyShared)
296 : 0 : return UPDATE_SOURCE_NONE;
297 : 0 : UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
298 : :
299 [ # # ]: 0 : if (!sharedVersion.isEmpty())
300 : : {
301 : : int index = determineHighestVersion(
302 [ # # ]: 0 : OUString(), sharedVersion, bundledVersion, onlineVersion);
303 [ # # ]: 0 : if (index == 2)
304 : 0 : retVal = UPDATE_SOURCE_BUNDLED;
305 [ # # ]: 0 : else if (index == 3)
306 : 0 : retVal = UPDATE_SOURCE_ONLINE;
307 : : }
308 : 0 : return retVal;
309 : : }
310 : :
311 : : Reference<deployment::XPackage>
312 : 0 : getExtensionWithHighestVersion(
313 : : Sequence<Reference<deployment::XPackage> > const & seqExt)
314 : : {
315 [ # # ]: 0 : if (seqExt.getLength() == 0)
316 : 0 : return Reference<deployment::XPackage>();
317 : :
318 : 0 : Reference<deployment::XPackage> greatest;
319 : 0 : sal_Int32 len = seqExt.getLength();
320 : :
321 [ # # ]: 0 : for (sal_Int32 i = 0; i < len; i++)
322 : : {
323 [ # # ]: 0 : if (!greatest.is())
324 : : {
325 [ # # ]: 0 : greatest = seqExt[i];
326 : 0 : continue;
327 : : }
328 : 0 : Reference<deployment::XPackage> const & current = seqExt[i];
329 : : //greatest has a value
330 [ # # ]: 0 : if (! current.is())
331 : 0 : continue;
332 : :
333 [ # # ][ # # ]: 0 : if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER)
[ # # ][ # # ]
[ # # ][ # # ]
334 [ # # ]: 0 : greatest = current;
335 : : }
336 : 0 : return greatest;
337 : : }
338 : :
339 : 0 : UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext):
340 : 0 : extension(ext)
341 : : {
342 : 0 : }
343 : :
344 : :
345 : :
346 : 0 : UpdateInfoMap getOnlineUpdateInfos(
347 : : Reference<uno::XComponentContext> const &xContext,
348 : : Reference<deployment::XExtensionManager> const & xExtMgr,
349 : : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
350 : : std::vector<Reference<deployment::XPackage > > const * extensionList,
351 : : std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors)
352 : : {
353 : : OSL_ASSERT(xExtMgr.is());
354 [ # # ]: 0 : UpdateInfoMap infoMap;
355 [ # # ][ # # ]: 0 : if (!xExtMgr.is() || onlyBundledExtensions(xExtMgr, extensionList))
[ # # ][ # # ]
356 : : return infoMap;
357 : :
358 [ # # ]: 0 : if (!extensionList)
359 : : {
360 [ # # ]: 0 : const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions(
361 [ # # ]: 0 : Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
362 : :
363 : : //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo
364 [ # # ]: 0 : for (int pos = seqAllExt.getLength(); pos --; )
365 : : {
366 : 0 : uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos];
367 : :
368 [ # # ]: 0 : Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt);
369 : : OSL_ASSERT(extension.is());
370 : :
371 : : std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
372 : : UpdateInfoMap::value_type(
373 [ # # ][ # # ]: 0 : dp_misc::getIdentifier(extension), UpdateInfo(extension)));
[ # # ][ # # ]
[ # # ][ # # ]
374 : : OSL_ASSERT(insertRet.second == true);
375 : : (void)insertRet;
376 [ # # ]: 0 : }
377 : : }
378 : : else
379 : : {
380 : : typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT;
381 [ # # ][ # # ]: 0 : for (CIT i = extensionList->begin(); i != extensionList->end(); ++i)
382 : : {
383 : : OSL_ASSERT(i->is());
384 : : std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
385 : : UpdateInfoMap::value_type(
386 [ # # ][ # # ]: 0 : dp_misc::getIdentifier(*i), UpdateInfo(*i)));
[ # # ][ # # ]
[ # # ][ # # ]
387 : : OSL_ASSERT(insertRet.second == true);
388 : : (void)insertRet;
389 : : }
390 : : }
391 : :
392 : : //Now find the update information for the extensions which provide their own
393 : : //URLs to update information.
394 : 0 : bool allInfosObtained = false;
395 [ # # ]: 0 : getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, allInfosObtained);
396 : :
397 [ # # ]: 0 : if (!allInfosObtained)
398 [ # # ]: 0 : getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors);
399 : 0 : return infoMap;
400 : : }
401 : 0 : OUString getHighestVersion(
402 : : ::rtl::OUString const & userVersion,
403 : : ::rtl::OUString const & sharedVersion,
404 : : ::rtl::OUString const & bundledVersion,
405 : : ::rtl::OUString const & onlineVersion)
406 : : {
407 : 0 : int index = determineHighestVersion(userVersion, sharedVersion, bundledVersion, onlineVersion);
408 [ # # # # : 0 : switch (index)
# ]
409 : : {
410 : 0 : case 0: return userVersion;
411 : 0 : case 1: return sharedVersion;
412 : 0 : case 2: return bundledVersion;
413 : 0 : case 3: return onlineVersion;
414 : : default: OSL_ASSERT(0);
415 : : }
416 : :
417 : 0 : return OUString();
418 : : }
419 : : } //namespace dp_misc
420 : :
421 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|