merge the formfield patch from ooo-build
[ooovba.git] / desktop / source / deployment / manager / dp_informationprovider.cxx
blob16a502b7b6448545af2389117ccdafb7c62a7231
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
31 #include <cppuhelper/implbase3.hxx>
33 #include "comphelper/servicedecl.hxx"
35 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
36 #include "com/sun/star/deployment/UpdateInformationProvider.hpp"
37 #include "com/sun/star/deployment/XPackage.hpp"
38 #include "com/sun/star/deployment/XPackageInformationProvider.hpp"
39 #include "com/sun/star/deployment/XPackageManager.hpp"
40 #include "com/sun/star/deployment/XUpdateInformationProvider.hpp"
41 #include "com/sun/star/lang/XServiceInfo.hpp"
42 #include "com/sun/star/registry/XRegistryKey.hpp"
43 #include "com/sun/star/task/XAbortChannel.hpp"
44 #include "com/sun/star/ucb/CommandFailedException.hpp"
45 #include "com/sun/star/ucb/XCommandEnvironment.hpp"
46 #include "com/sun/star/uno/XComponentContext.hpp"
47 #include "com/sun/star/xml/dom/XElement.hpp"
48 #include "com/sun/star/xml/dom/XNode.hpp"
50 #include "com/sun/star/uno/Reference.hxx"
51 #include "rtl/ustring.hxx"
52 #include "ucbhelper/content.hxx"
54 #include "dp_dependencies.hxx"
55 #include "dp_descriptioninfoset.hxx"
56 #include "dp_identifier.hxx"
57 #include "dp_version.hxx"
58 #include "dp_misc.h"
60 namespace beans = com::sun::star::beans ;
61 namespace deployment = com::sun::star::deployment ;
62 namespace lang = com::sun::star::lang ;
63 namespace registry = com::sun::star::registry ;
64 namespace task = com::sun::star::task ;
65 namespace css_ucb = com::sun::star::ucb ;
66 namespace uno = com::sun::star::uno ;
67 namespace xml = com::sun::star::xml ;
69 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
71 namespace dp_info {
73 class PackageInformationProvider :
74 public ::cppu::WeakImplHelper3< deployment::XPackageInformationProvider,
75 css_ucb::XCommandEnvironment,
76 task::XInteractionHandler >
78 public:
79 PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext);
80 virtual ~PackageInformationProvider();
82 static uno::Sequence< rtl::OUString > getServiceNames();
83 static rtl::OUString getImplName();
85 // XInteractionHandler
86 virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& Request )
87 throw( uno::RuntimeException );
88 // XCommandEnvironment
89 virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
90 throw ( uno::RuntimeException ) { return static_cast<task::XInteractionHandler*>(this); };
92 virtual uno::Reference< css_ucb::XProgressHandler > SAL_CALL getProgressHandler()
93 throw ( uno::RuntimeException ) { return uno::Reference< css_ucb::XProgressHandler >(); };
95 // XPackageInformationProvider
96 virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId )
97 throw ( uno::RuntimeException );
98 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId )
99 throw ( uno::RuntimeException );
100 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList()
101 throw ( uno::RuntimeException );
102 //---------
103 private:
105 uno::Reference< uno::XComponentContext> mxContext;
107 rtl::OUString getPackageLocation( const uno::Reference< deployment::XPackageManager > _xManager,
108 const rtl::OUString& _sExtensionId );
110 uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation;
112 uno::Sequence< uno::Reference< xml::dom::XElement > >
113 getUpdateInformation( uno::Sequence< rtl::OUString > const & urls,
114 rtl::OUString const & identifier ) const;
115 uno::Sequence< uno::Reference< deployment::XPackage > >
116 getPackages( const uno::Reference< deployment::XPackageManager > _xManager );
117 uno::Sequence< uno::Sequence< rtl::OUString > > isUpdateAvailable( const uno::Reference< deployment::XPackageManager > _xManager,
118 const rtl::OUString& _sExtensionId );
119 uno::Sequence< uno::Sequence< rtl::OUString > > getExtensionList( const uno::Reference< deployment::XPackageManager > _xManager );
120 uno::Sequence< uno::Sequence< rtl::OUString > > concatLists( uno::Sequence< uno::Sequence< rtl::OUString > > aFirst,
121 uno::Sequence< uno::Sequence< rtl::OUString > > aSecond );
124 //------------------------------------------------------------------------------
126 PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) :
127 mxContext( xContext ),
128 mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) )
132 //------------------------------------------------------------------------------
134 PackageInformationProvider::~PackageInformationProvider()
138 //------------------------------------------------------------------------------
139 void SAL_CALL PackageInformationProvider::handle( uno::Reference< task::XInteractionRequest > const & rRequest)
140 throw (uno::RuntimeException)
142 uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations();
143 if ( xContinuations.getLength() == 1 )
145 xContinuations[0]->select();
149 //------------------------------------------------------------------------------
150 rtl::OUString PackageInformationProvider::getPackageLocation(
151 const uno::Reference< deployment::XPackageManager > _xManager,
152 const rtl::OUString& _rExtensionId )
154 rtl::OUString aLocationURL;
156 if ( _xManager.is() )
158 const uno::Sequence< uno::Reference< deployment::XPackage > > packages(
159 _xManager->getDeployedPackages(
160 uno::Reference< task::XAbortChannel >(),
161 static_cast < XCommandEnvironment *> (this) ) );
163 for ( int pos = packages.getLength(); pos--; )
167 const rtl::OUString aName = packages[ pos ]->getName();
168 const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier();
169 if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 )
171 aLocationURL = packages[ pos ]->getURL();
172 break;
175 catch ( uno::RuntimeException & ) {}
179 return aLocationURL;
182 //------------------------------------------------------------------------------
183 //------------------------------------------------------------------------------
184 //------------------------------------------------------------------------------
186 rtl::OUString SAL_CALL
187 PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId )
188 throw ( uno::RuntimeException )
190 uno::Reference< deployment::XPackageManager > xManager;
191 try {
192 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("user") );
194 catch ( css_ucb::CommandFailedException & ){}
195 catch ( uno::RuntimeException & ) {}
197 rtl::OUString aLocationURL = getPackageLocation( xManager, _sExtensionId );
199 if ( aLocationURL.getLength() == 0 )
201 try {
202 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("shared") );
204 catch ( css_ucb::CommandFailedException & ){}
205 catch ( uno::RuntimeException & ) {}
207 aLocationURL = getPackageLocation( xManager, _sExtensionId );
210 if ( aLocationURL.getLength() )
212 ::ucbhelper::Content aContent( aLocationURL, NULL );
213 aLocationURL = aContent.getURL();
216 return aLocationURL;
219 //------------------------------------------------------------------------------
221 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL
222 PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId )
223 throw ( uno::RuntimeException )
225 uno::Sequence< uno::Sequence< rtl::OUString > > aUpdateListUser;
227 uno::Reference< deployment::XPackageManager > xManager;
228 try {
229 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("user") );
231 catch ( css_ucb::CommandFailedException & ){}
232 catch ( uno::RuntimeException & ) {}
234 aUpdateListUser = isUpdateAvailable( xManager, _sExtensionId );
236 uno::Sequence< uno::Sequence< rtl::OUString > > aUpdateListShared;
237 try {
238 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("shared") );
240 catch ( css_ucb::CommandFailedException & ){}
241 catch ( uno::RuntimeException & ) {}
243 aUpdateListShared = isUpdateAvailable( xManager, _sExtensionId );
245 if ( !aUpdateListUser.hasElements() )
246 return aUpdateListShared;
247 else if ( !aUpdateListShared.hasElements() )
248 return aUpdateListUser;
249 else
250 return concatLists( aUpdateListUser, aUpdateListShared );
253 //------------------------------------------------------------------------------
254 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList()
255 throw ( uno::RuntimeException )
257 uno::Sequence< uno::Sequence< rtl::OUString > > aListUser;
259 uno::Reference< deployment::XPackageManager > xManager;
260 try {
261 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("user") );
263 catch ( css_ucb::CommandFailedException & ){}
264 catch ( uno::RuntimeException & ) {}
266 aListUser = getExtensionList( xManager );
268 uno::Sequence< uno::Sequence< rtl::OUString > > aListShared;
269 try {
270 xManager = deployment::thePackageManagerFactory::get( mxContext )->getPackageManager( UNISTRING("shared") );
272 catch ( css_ucb::CommandFailedException & ){}
273 catch ( uno::RuntimeException & ) {}
275 aListShared = getExtensionList( xManager );
277 if ( !aListUser.hasElements() )
278 return aListShared;
279 else if ( !aListShared.hasElements() )
280 return aListUser;
281 else
282 return concatLists( aListUser, aListShared );
285 //------------------------------------------------------------------------------
286 //------------------------------------------------------------------------------
287 //------------------------------------------------------------------------------
288 uno::Sequence< uno::Reference< deployment::XPackage > >
289 PackageInformationProvider::getPackages( const uno::Reference< deployment::XPackageManager > _xMgr )
291 uno::Sequence< uno::Reference< deployment::XPackage > > packages;
292 try {
293 packages = _xMgr->getDeployedPackages( uno::Reference< task::XAbortChannel >(),
294 static_cast < XCommandEnvironment *> (this) );
296 catch ( deployment::DeploymentException & )
298 catch ( css_ucb::CommandFailedException & )
300 catch ( css_ucb::CommandAbortedException & )
302 catch ( lang::IllegalArgumentException & e )
304 throw uno::RuntimeException(e.Message, e.Context);
307 return packages;
310 //------------------------------------------------------------------------------
311 uno::Sequence< uno::Reference< xml::dom::XElement > >
312 PackageInformationProvider::getUpdateInformation( uno::Sequence< rtl::OUString > const & urls,
313 rtl::OUString const & identifier ) const
317 return mxUpdateInformation->getUpdateInformation( urls, identifier );
319 catch ( uno::RuntimeException & ) {
320 throw;
322 catch ( css_ucb::CommandFailedException & ) {}
323 catch ( css_ucb::CommandAbortedException & ) {}
324 catch ( uno::Exception & ) {}
326 return uno::Sequence< uno::Reference< xml::dom::XElement > >();
329 //------------------------------------------------------------------------------
330 uno::Sequence< uno::Sequence< rtl::OUString > >
331 PackageInformationProvider::isUpdateAvailable(
332 const uno::Reference< deployment::XPackageManager > _xManager,
333 const rtl::OUString& _sExtensionId )
335 uno::Sequence< uno::Sequence< rtl::OUString > > aList;
336 sal_Int32 nCount = 0;
337 bool bPackageFound = false;
339 // If the package manager is readonly then the user cannot modify anything anyway
340 // so we can abort the search here
341 if ( _xManager.is() && ! _xManager->isReadOnly() )
343 uno::Sequence< uno::Reference< deployment::XPackage > > packages( getPackages( _xManager ) );
344 uno::Sequence< uno::Reference< xml::dom::XElement > > defaultInfos;
346 for ( int pos = packages.getLength(); pos-- && !bPackageFound; )
348 uno::Reference< deployment::XPackage > package( packages[ pos ] );
349 uno::Sequence< rtl::OUString > urls( package->getUpdateInformationURLs());
350 uno::Sequence< uno::Reference< xml::dom::XElement > > infos;
351 rtl::OUString id( dp_misc::getIdentifier( package ) );
353 if ( _sExtensionId.getLength() )
355 if ( _sExtensionId == id )
356 bPackageFound = true;
357 else /* we have an ID and the IDs don't match, continue with next package */
358 continue;
361 if ( urls.getLength() != 0)
363 infos = getUpdateInformation( urls, id );
365 else
367 if ( defaultInfos.getLength() == 0 )
369 const rtl::OUString defaultURL( dp_misc::getExtensionDefaultUpdateURL() );
370 if ( defaultURL.getLength() )
371 defaultInfos = getUpdateInformation( uno::Sequence< rtl::OUString >( &defaultURL, 1 ),
372 rtl::OUString() );
374 infos = defaultInfos;
376 rtl::OUString latestVersion( package->getVersion() );
377 sal_Int32 latestIndex = -1;
378 for ( sal_Int32 i = 0; i < infos.getLength(); ++i )
380 dp_misc::DescriptionInfoset infoset( mxContext,
381 uno::Reference< xml::dom::XNode >( infos[i], uno::UNO_QUERY_THROW));
382 boost::optional< rtl::OUString > id2( infoset.getIdentifier() );
384 if (!id2)
385 continue;
387 if (*id2 == id)
389 // check, if there are unsatisfied dependencies and ignore those updates
390 uno::Sequence< uno::Reference< xml::dom::XElement > > ds( dp_misc::Dependencies::check( infoset ) );
391 if ( ds.getLength() )
392 continue;
394 rtl::OUString v( infoset.getVersion() );
395 if ( dp_misc::compareVersions( v, latestVersion ) == dp_misc::GREATER )
397 latestVersion = v;
398 latestIndex = i;
402 if ( latestIndex != -1 )
404 rtl::OUString aNewEntry[2];
405 aNewEntry[0] = id;
406 aNewEntry[1] = latestVersion;
407 aList.realloc( ++nCount );
408 aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 );
412 return aList;
415 //------------------------------------------------------------------------------
416 uno::Sequence< uno::Sequence< rtl::OUString > >
417 PackageInformationProvider::getExtensionList(
418 const uno::Reference< deployment::XPackageManager > _xManager )
420 uno::Sequence< uno::Sequence< rtl::OUString > > aList;
422 if ( _xManager.is() )
424 uno::Sequence< uno::Reference< deployment::XPackage > > packages( getPackages( _xManager ) );
426 aList.realloc( packages.getLength() );
428 for ( int pos = packages.getLength(); pos--; )
430 uno::Reference< deployment::XPackage > package( packages[ pos ] );
431 rtl::OUString aNewEntry[2];
433 aNewEntry[0] = dp_misc::getIdentifier( package );
434 aNewEntry[1] = package->getVersion();
435 aList[ pos ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 );
438 return aList;
441 //------------------------------------------------------------------------------
442 uno::Sequence< uno::Sequence< rtl::OUString > > PackageInformationProvider::concatLists(
443 uno::Sequence< uno::Sequence< rtl::OUString > > aFirst,
444 uno::Sequence< uno::Sequence< rtl::OUString > > aSecond )
446 sal_Int32 nFirstCount = aFirst.getLength();
447 sal_Int32 nSecondCount = aSecond.getLength();
448 sal_Int32 nIndex = nFirstCount;
450 for ( sal_Int32 i=0; i < nSecondCount; i++ )
452 bool bDuplicateEntry = false;
453 for ( sal_Int32 j=0; j < nFirstCount; j++ )
455 if ( aFirst[ j ][0] == aSecond[ i ][0] )
457 bDuplicateEntry = true;
458 break;
461 if ( !bDuplicateEntry )
463 nIndex += 1;
464 aFirst.realloc( nIndex );
465 aFirst[ nIndex - 1 ] = aSecond[ i ];
468 return aFirst;
471 //------------------------------------------------------------------------------
472 //------------------------------------------------------------------------------
473 //------------------------------------------------------------------------------
475 namespace sdecl = comphelper::service_decl;
476 sdecl::class_<PackageInformationProvider> servicePIP;
477 extern sdecl::ServiceDecl const serviceDecl(
478 servicePIP,
479 // a private one:
480 "com.sun.star.comp.deployment.PackageInformationProvider",
481 "com.sun.star.comp.deployment.PackageInformationProvider" );
483 //------------------------------------------------------------------------------
484 bool singleton_entries(
485 uno::Reference< registry::XRegistryKey > const & xRegistryKey )
487 try {
488 uno::Reference< registry::XRegistryKey > xKey(
489 xRegistryKey->createKey(
490 serviceDecl.getImplementationName() +
491 // xxx todo: use future generated function to get singleton name
492 UNISTRING("/UNO/SINGLETONS/"
493 "com.sun.star.deployment.PackageInformationProvider") ) );
494 xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] );
495 return true;
497 catch (registry::InvalidRegistryException & exc) {
498 (void) exc; // avoid warnings
499 OSL_ENSURE( 0, ::rtl::OUStringToOString(
500 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
501 return false;
505 } // namespace dp_info