1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
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))
73 class PackageInformationProvider
:
74 public ::cppu::WeakImplHelper3
< deployment::XPackageInformationProvider
,
75 css_ucb::XCommandEnvironment
,
76 task::XInteractionHandler
>
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
);
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();
175 catch ( uno::RuntimeException
& ) {}
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
;
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 )
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();
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
;
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
;
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
;
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
;
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
;
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() )
279 else if ( !aListShared
.hasElements() )
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
;
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
);
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
& ) {
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 */
361 if ( urls
.getLength() != 0)
363 infos
= getUpdateInformation( urls
, id
);
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 ),
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() );
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() )
394 rtl::OUString
v( infoset
.getVersion() );
395 if ( dp_misc::compareVersions( v
, latestVersion
) == dp_misc::GREATER
)
402 if ( latestIndex
!= -1 )
404 rtl::OUString aNewEntry
[2];
406 aNewEntry
[1] = latestVersion
;
407 aList
.realloc( ++nCount
);
408 aList
[ nCount
-1 ] = ::uno::Sequence
< rtl::OUString
>( aNewEntry
, 2 );
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 );
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;
461 if ( !bDuplicateEntry
)
464 aFirst
.realloc( nIndex
);
465 aFirst
[ nIndex
- 1 ] = aSecond
[ i
];
471 //------------------------------------------------------------------------------
472 //------------------------------------------------------------------------------
473 //------------------------------------------------------------------------------
475 namespace sdecl
= comphelper::service_decl
;
476 sdecl::class_
<PackageInformationProvider
> servicePIP
;
477 extern sdecl::ServiceDecl
const serviceDecl(
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
)
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] );
497 catch (registry::InvalidRegistryException
& exc
) {
498 (void) exc
; // avoid warnings
499 OSL_ENSURE( 0, ::rtl::OUStringToOString(
500 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
505 } // namespace dp_info