xref: /trunk/main/desktop/source/deployment/manager/dp_informationprovider.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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