1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26
27 #include <cppuhelper/implbase3.hxx>
28
29 #include "comphelper/servicedecl.hxx"
30
31 #include "com/sun/star/deployment/UpdateInformationProvider.hpp"
32 #include "com/sun/star/deployment/XPackage.hpp"
33 #include "com/sun/star/deployment/XPackageInformationProvider.hpp"
34 #include "com/sun/star/deployment/ExtensionManager.hpp"
35 #include "com/sun/star/deployment/XUpdateInformationProvider.hpp"
36 #include "com/sun/star/lang/XServiceInfo.hpp"
37 #include "com/sun/star/registry/XRegistryKey.hpp"
38 #include "com/sun/star/task/XAbortChannel.hpp"
39 #include "com/sun/star/uno/XComponentContext.hpp"
40 #include "com/sun/star/ucb/XCommandEnvironment.hpp"
41 #include "com/sun/star/xml/dom/XElement.hpp"
42 #include "com/sun/star/xml/dom/XNode.hpp"
43
44 #include "com/sun/star/uno/Reference.hxx"
45 #include "rtl/ustring.hxx"
46 #include "ucbhelper/content.hxx"
47
48 #include "dp_dependencies.hxx"
49 #include "dp_descriptioninfoset.hxx"
50 #include "dp_identifier.hxx"
51 #include "dp_version.hxx"
52 #include "dp_misc.h"
53 #include "dp_update.hxx"
54
55 namespace beans = com::sun::star::beans ;
56 namespace deployment = com::sun::star::deployment ;
57 namespace lang = com::sun::star::lang ;
58 namespace registry = com::sun::star::registry ;
59 namespace task = com::sun::star::task ;
60 namespace css_ucb = com::sun::star::ucb ;
61 namespace uno = com::sun::star::uno ;
62 namespace xml = com::sun::star::xml ;
63
64 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
65
66 namespace dp_info {
67
68 class PackageInformationProvider :
69 public ::cppu::WeakImplHelper1< deployment::XPackageInformationProvider >
70
71 {
72 public:
73 PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext);
74 virtual ~PackageInformationProvider();
75
76 static uno::Sequence< rtl::OUString > getServiceNames();
77 static rtl::OUString getImplName();
78
79 // XPackageInformationProvider
80 virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId );
81 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId );
82 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList();
83 //---------
84 private:
85
86 uno::Reference< uno::XComponentContext> mxContext;
87
88 rtl::OUString getPackageLocation( const rtl::OUString& repository,
89 const rtl::OUString& _sExtensionId );
90
91 uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation;
92 };
93
94 //------------------------------------------------------------------------------
95
PackageInformationProvider(uno::Reference<uno::XComponentContext> const & xContext)96 PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) :
97 mxContext( xContext ),
98 mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) )
99 {
100 }
101
102 //------------------------------------------------------------------------------
103
~PackageInformationProvider()104 PackageInformationProvider::~PackageInformationProvider()
105 {
106 }
107
108 //------------------------------------------------------------------------------
getPackageLocation(const rtl::OUString & repository,const rtl::OUString & _rExtensionId)109 rtl::OUString PackageInformationProvider::getPackageLocation(
110 const rtl::OUString & repository,
111 const rtl::OUString& _rExtensionId )
112 {
113 rtl::OUString aLocationURL;
114 uno::Reference<deployment::XExtensionManager> xManager =
115 deployment::ExtensionManager::get(mxContext);
116
117 if ( xManager.is() )
118 {
119 const uno::Sequence< uno::Reference< deployment::XPackage > > packages(
120 xManager->getDeployedExtensions(
121 repository,
122 uno::Reference< task::XAbortChannel >(),
123 uno::Reference< css_ucb::XCommandEnvironment > () ) );
124
125 for ( int pos = packages.getLength(); pos--; )
126 {
127 try
128 {
129 const rtl::OUString aName = packages[ pos ]->getName();
130 const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier();
131 if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 )
132 {
133 aLocationURL = packages[ pos ]->getURL();
134 break;
135 }
136 }
137 catch ( uno::RuntimeException & ) {}
138 }
139 }
140
141 return aLocationURL;
142 }
143
144 //------------------------------------------------------------------------------
145 //------------------------------------------------------------------------------
146 //------------------------------------------------------------------------------
147
148 rtl::OUString SAL_CALL
getPackageLocation(const rtl::OUString & _sExtensionId)149 PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId )
150 {
151 rtl::OUString aLocationURL = getPackageLocation( UNISTRING("user"), _sExtensionId );
152
153 if ( aLocationURL.getLength() == 0 )
154 {
155 aLocationURL = getPackageLocation( UNISTRING("shared"), _sExtensionId );
156 }
157 if ( aLocationURL.getLength() == 0 )
158 {
159 aLocationURL = getPackageLocation( UNISTRING("bundled"), _sExtensionId );
160 }
161 if ( aLocationURL.getLength() == 0 )
162 {
163 aLocationURL = getPackageLocation( UNISTRING("bundled_prereg"), _sExtensionId );
164 }
165 if ( aLocationURL.getLength() )
166 {
167 ::ucbhelper::Content aContent( aLocationURL, NULL );
168 aLocationURL = aContent.getURL();
169 }
170 return aLocationURL;
171 }
172
173 //------------------------------------------------------------------------------
174
175 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL
isUpdateAvailable(const rtl::OUString & _sExtensionId)176 PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId )
177 {
178 uno::Sequence< uno::Sequence< rtl::OUString > > aList;
179
180 uno::Reference<deployment::XExtensionManager> extMgr =
181 deployment::ExtensionManager::get(mxContext);
182
183 if (!extMgr.is())
184 {
185 OSL_ASSERT(0);
186 return aList;
187 }
188 std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors;
189 dp_misc::UpdateInfoMap updateInfoMap;
190 if (_sExtensionId.getLength())
191 {
192 std::vector<uno::Reference<deployment::XPackage> > vecExtensions;
193 uno::Reference<deployment::XPackage> extension;
194 try
195 {
196 extension = dp_misc::getExtensionWithHighestVersion(
197 extMgr->getExtensionsWithSameIdentifier(
198 _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>()));
199 vecExtensions.push_back(extension);
200 }
201 catch (lang::IllegalArgumentException &)
202 {
203 OSL_ASSERT(0);
204 }
205 updateInfoMap = dp_misc::getOnlineUpdateInfos(
206 mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors);
207 }
208 else
209 {
210 updateInfoMap = dp_misc::getOnlineUpdateInfos(
211 mxContext, extMgr, mxUpdateInformation, NULL, errors);
212 }
213
214 int nCount = 0;
215 for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++)
216 {
217 dp_misc::UpdateInfo const & info = i->second;
218
219 rtl::OUString sOnlineVersion;
220 if (info.info.is())
221 {
222 // check, if there are unsatisfied dependencies and ignore this online update
223 dp_misc::DescriptionInfoset infoset(mxContext, info.info);
224 uno::Sequence< uno::Reference< xml::dom::XElement > >
225 ds( dp_misc::Dependencies::check( infoset ) );
226 if ( ! ds.getLength() )
227 sOnlineVersion = info.version;
228 }
229
230 rtl::OUString sVersionUser;
231 rtl::OUString sVersionShared;
232 rtl::OUString sVersionBundled;
233 uno::Sequence< uno::Reference< deployment::XPackage> > extensions;
234 try {
235 extensions = extMgr->getExtensionsWithSameIdentifier(
236 dp_misc::getIdentifier(info.extension), info.extension->getName(),
237 uno::Reference<css_ucb::XCommandEnvironment>());
238 } catch (lang::IllegalArgumentException& ) {
239 OSL_ASSERT(0);
240 }
241 OSL_ASSERT(extensions.getLength() == 3);
242 if (extensions[0].is() )
243 sVersionUser = extensions[0]->getVersion();
244 if (extensions[1].is() )
245 sVersionShared = extensions[1]->getVersion();
246 if (extensions[2].is() )
247 sVersionBundled = extensions[2]->getVersion();
248
249 bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared"));
250
251 dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension(
252 bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion);
253 dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension(
254 bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion);
255
256 rtl::OUString updateVersionUser;
257 rtl::OUString updateVersionShared;
258 if (sourceUser != dp_misc::UPDATE_SOURCE_NONE)
259 updateVersionUser = dp_misc::getHighestVersion(
260 rtl::OUString(), sVersionShared, sVersionBundled, sOnlineVersion);
261 if (sourceShared != dp_misc::UPDATE_SOURCE_NONE)
262 updateVersionShared = dp_misc::getHighestVersion(
263 rtl::OUString(), rtl::OUString(), sVersionBundled, sOnlineVersion);
264 rtl::OUString updateVersion;
265 if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER)
266 updateVersion = updateVersionUser;
267 else
268 updateVersion = updateVersionShared;
269 if (updateVersion.getLength())
270 {
271
272 rtl::OUString aNewEntry[2];
273 aNewEntry[0] = i->first;
274 aNewEntry[1] = updateVersion;
275 aList.realloc( ++nCount );
276 aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 );
277 }
278 }
279 return aList;
280 }
281
282 //------------------------------------------------------------------------------
getExtensionList()283 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList()
284 {
285 const uno::Reference<deployment::XExtensionManager> mgr =
286 deployment::ExtensionManager::get(mxContext);
287
288 if (!mgr.is())
289 return uno::Sequence< uno::Sequence< rtl::OUString > >();
290
291 const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > >
292 allExt = mgr->getAllExtensions(
293 uno::Reference< task::XAbortChannel >(),
294 uno::Reference< css_ucb::XCommandEnvironment > () );
295
296 uno::Sequence< uno::Sequence< rtl::OUString > > retList;
297
298 sal_Int32 cAllIds = allExt.getLength();
299 retList.realloc(cAllIds);
300
301 for (sal_Int32 i = 0; i < cAllIds; i++)
302 {
303 //The inner sequence contains extensions with the same identifier from
304 //all the different repositories, that is user, share, bundled.
305 const uno::Sequence< uno::Reference< deployment::XPackage > > &
306 seqExtension = allExt[i];
307 sal_Int32 cExt = seqExtension.getLength();
308 OSL_ASSERT(cExt == 3);
309 for (sal_Int32 j = 0; j < cExt; j++)
310 {
311 //ToDo according to the old code the first found extenions is used
312 //even if another one with the same id has a better version.
313 uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] );
314 if (xExtension.is())
315 {
316 rtl::OUString aNewEntry[2];
317 aNewEntry[0] = dp_misc::getIdentifier(xExtension);
318 aNewEntry[1] = xExtension->getVersion();
319 retList[i] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 );
320 break;
321 }
322 }
323 }
324 return retList;
325 }
326
327
328 //------------------------------------------------------------------------------
329 //------------------------------------------------------------------------------
330 //------------------------------------------------------------------------------
331
332 namespace sdecl = comphelper::service_decl;
333 sdecl::class_<PackageInformationProvider> servicePIP;
334 extern sdecl::ServiceDecl const serviceDecl(
335 servicePIP,
336 // a private one:
337 "com.sun.star.comp.deployment.PackageInformationProvider",
338 "com.sun.star.comp.deployment.PackageInformationProvider" );
339
340 //------------------------------------------------------------------------------
singleton_entries(uno::Reference<registry::XRegistryKey> const & xRegistryKey)341 bool singleton_entries(
342 uno::Reference< registry::XRegistryKey > const & xRegistryKey )
343 {
344 try {
345 uno::Reference< registry::XRegistryKey > xKey(
346 xRegistryKey->createKey(
347 serviceDecl.getImplementationName() +
348 // xxx todo: use future generated function to get singleton name
349 UNISTRING("/UNO/SINGLETONS/"
350 "com.sun.star.deployment.PackageInformationProvider") ) );
351 xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] );
352 return true;
353 }
354 catch (registry::InvalidRegistryException & exc) {
355 (void) exc; // avoid warnings
356 OSL_ENSURE( 0, ::rtl::OUStringToOString(
357 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
358 return false;
359 }
360 }
361
362 } // namespace dp_info
363