bump product version to 4.1.6.2
[LibreOffice.git] / desktop / source / app / check_ext_deps.cxx
blobbb9aadb31477166d7f4a1d8eca44181096dde353
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "osl/file.hxx"
21 #include "osl/mutex.hxx"
23 #include <rtl/bootstrap.hxx>
24 #include <rtl/ustring.hxx>
25 #include <rtl/logfile.hxx>
26 #include "cppuhelper/compbase3.hxx"
28 #include "vcl/wrkwin.hxx"
29 #include "vcl/timer.hxx"
31 #include <unotools/configmgr.hxx>
32 #include "toolkit/helper/vclunohelper.hxx"
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <cppuhelper/bootstrap.hxx>
37 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/NamedValue.hpp>
40 #include <com/sun/star/configuration/theDefaultProvider.hpp>
41 #include "com/sun/star/deployment/XPackage.hpp"
42 #include "com/sun/star/deployment/ExtensionManager.hpp"
43 #include "com/sun/star/deployment/LicenseException.hpp"
44 #include "com/sun/star/deployment/ui/LicenseDialog.hpp"
45 #include <com/sun/star/task/OfficeRestartManager.hpp>
46 #include <com/sun/star/task/XJob.hpp>
47 #include <com/sun/star/task/XJobExecutor.hpp>
48 #include <com/sun/star/task/XInteractionApprove.hpp>
49 #include <com/sun/star/task/XInteractionAbort.hpp>
50 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
51 #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
52 #include <com/sun/star/util/XChangesBatch.hpp>
54 #include "app.hxx"
56 #include "../deployment/inc/dp_misc.h"
58 using namespace desktop;
59 using namespace com::sun::star;
60 using namespace com::sun::star::lang;
61 using namespace com::sun::star::task;
62 using namespace com::sun::star::uno;
64 namespace
66 //For use with XExtensionManager.synchronize
67 class SilentCommandEnv
68 : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment,
69 task::XInteractionHandler,
70 ucb::XProgressHandler >
72 uno::Reference<uno::XComponentContext> mxContext;
73 Desktop *mpDesktop;
74 sal_Int32 mnLevel;
75 sal_Int32 mnProgress;
77 public:
78 SilentCommandEnv(
79 uno::Reference<uno::XComponentContext> const & xContext,
80 Desktop* pDesktop );
81 virtual ~SilentCommandEnv();
83 // XCommandEnvironment
84 virtual uno::Reference<task::XInteractionHandler > SAL_CALL
85 getInteractionHandler() throw (uno::RuntimeException);
86 virtual uno::Reference<ucb::XProgressHandler >
87 SAL_CALL getProgressHandler() throw (uno::RuntimeException);
89 // XInteractionHandler
90 virtual void SAL_CALL handle(
91 uno::Reference<task::XInteractionRequest > const & xRequest )
92 throw (uno::RuntimeException);
94 // XProgressHandler
95 virtual void SAL_CALL push( uno::Any const & Status )
96 throw (uno::RuntimeException);
97 virtual void SAL_CALL update( uno::Any const & Status )
98 throw (uno::RuntimeException);
99 virtual void SAL_CALL pop() throw (uno::RuntimeException);
102 //-----------------------------------------------------------------------------
103 SilentCommandEnv::SilentCommandEnv(
104 uno::Reference<uno::XComponentContext> const & xContext,
105 Desktop* pDesktop ):
106 mxContext( xContext ),
107 mpDesktop( pDesktop ),
108 mnLevel( 0 ),
109 mnProgress( 25 )
112 //-----------------------------------------------------------------------------
113 SilentCommandEnv::~SilentCommandEnv()
115 mpDesktop->SetSplashScreenText( OUString() );
118 //-----------------------------------------------------------------------------
119 Reference<task::XInteractionHandler> SilentCommandEnv::getInteractionHandler()
120 throw (uno::RuntimeException)
122 return this;
125 //-----------------------------------------------------------------------------
126 Reference<ucb::XProgressHandler> SilentCommandEnv::getProgressHandler()
127 throw (uno::RuntimeException)
129 return this;
132 //-----------------------------------------------------------------------------
133 // XInteractionHandler
134 void SilentCommandEnv::handle( Reference< task::XInteractionRequest> const & xRequest )
135 throw (uno::RuntimeException)
137 deployment::LicenseException licExc;
139 uno::Any request( xRequest->getRequest() );
140 bool bApprove = true;
142 if ( request >>= licExc )
144 uno::Reference< ui::dialogs::XExecutableDialog > xDialog(
145 deployment::ui::LicenseDialog::create(
146 mxContext, VCLUnoHelper::GetInterface( NULL ),
147 licExc.ExtensionName, licExc.Text ) );
148 sal_Int16 res = xDialog->execute();
149 if ( res == ui::dialogs::ExecutableDialogResults::CANCEL )
150 bApprove = false;
151 else if ( res == ui::dialogs::ExecutableDialogResults::OK )
152 bApprove = true;
153 else
155 OSL_ASSERT(0);
159 // We approve everything here
160 uno::Sequence< Reference< task::XInteractionContinuation > > conts( xRequest->getContinuations() );
161 Reference< task::XInteractionContinuation > const * pConts = conts.getConstArray();
162 sal_Int32 len = conts.getLength();
164 for ( sal_Int32 pos = 0; pos < len; ++pos )
166 if ( bApprove )
168 uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY );
169 if ( xInteractionApprove.is() )
170 xInteractionApprove->select();
172 else
174 uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY );
175 if ( xInteractionAbort.is() )
176 xInteractionAbort->select();
181 //-----------------------------------------------------------------------------
182 // XProgressHandler
183 void SilentCommandEnv::push( uno::Any const & rStatus )
184 throw (uno::RuntimeException)
186 OUString sText;
187 mnLevel += 1;
189 if ( rStatus.hasValue() && ( rStatus >>= sText) )
191 if ( mnLevel <= 3 )
192 mpDesktop->SetSplashScreenText( sText );
193 else
194 mpDesktop->SetSplashScreenProgress( ++mnProgress );
198 //-----------------------------------------------------------------------------
199 void SilentCommandEnv::update( uno::Any const & rStatus )
200 throw (uno::RuntimeException)
202 OUString sText;
203 if ( rStatus.hasValue() && ( rStatus >>= sText) )
205 mpDesktop->SetSplashScreenText( sText );
209 //-----------------------------------------------------------------------------
210 void SilentCommandEnv::pop() throw (uno::RuntimeException)
212 mnLevel -= 1;
215 } // end namespace
218 static const char aAccessSrvc[] = "com.sun.star.configuration.ConfigurationUpdateAccess";
220 static sal_Int16 impl_showExtensionDialog( uno::Reference< uno::XComponentContext > &xContext )
222 OUString sServiceName = "com.sun.star.deployment.ui.UpdateRequiredDialog";
223 uno::Reference< uno::XInterface > xService;
224 sal_Int16 nRet = 0;
226 uno::Reference< lang::XMultiComponentFactory > xServiceManager( xContext->getServiceManager() );
227 if( !xServiceManager.is() )
228 throw uno::RuntimeException(
229 "impl_showExtensionDialog(): unable to obtain service manager from component context", uno::Reference< uno::XInterface > () );
231 xService = xServiceManager->createInstanceWithContext( sServiceName, xContext );
232 uno::Reference< ui::dialogs::XExecutableDialog > xExecuteable( xService, uno::UNO_QUERY );
233 if ( xExecuteable.is() )
234 nRet = xExecuteable->execute();
236 return nRet;
239 //------------------------------------------------------------------------------
240 // Check dependencies of all packages
241 //------------------------------------------------------------------------------
242 static bool impl_checkDependencies( const uno::Reference< uno::XComponentContext > &xContext )
244 uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
245 uno::Reference< deployment::XExtensionManager > xExtensionManager = deployment::ExtensionManager::get( xContext );
247 if ( !xExtensionManager.is() )
249 OSL_FAIL( "Could not get the Extension Manager!" );
250 return true;
253 try {
254 xAllPackages = xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
255 uno::Reference< ucb::XCommandEnvironment >() );
257 catch ( const deployment::DeploymentException & ) { return true; }
258 catch ( const ucb::CommandFailedException & ) { return true; }
259 catch ( const ucb::CommandAbortedException & ) { return true; }
260 catch ( const lang::IllegalArgumentException & e ) {
261 throw uno::RuntimeException( e.Message, e.Context );
264 sal_Int32 nMax = 2;
265 #ifdef DEBUG
266 nMax = 3;
267 #endif
269 for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
271 uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
273 for ( sal_Int32 j = 0; (j<nMax) && (j < xPackageList.getLength()); ++j )
275 uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
276 if ( xPackage.is() )
278 bool bRegistered = false;
279 try {
280 beans::Optional< beans::Ambiguous< sal_Bool > > option( xPackage->isRegistered( uno::Reference< task::XAbortChannel >(),
281 uno::Reference< ucb::XCommandEnvironment >() ) );
282 if ( option.IsPresent )
284 ::beans::Ambiguous< sal_Bool > const & reg = option.Value;
285 if ( reg.IsAmbiguous )
286 bRegistered = false;
287 else
288 bRegistered = reg.Value ? true : false;
290 else
291 bRegistered = false;
293 catch ( const uno::RuntimeException & ) { throw; }
294 catch (const uno::Exception & exc) {
295 (void) exc;
296 OSL_FAIL( OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
299 if ( bRegistered )
301 bool bDependenciesValid = false;
302 try {
303 bDependenciesValid = xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() );
305 catch ( const deployment::DeploymentException & ) {}
306 if ( ! bDependenciesValid )
308 return false;
314 return true;
317 //------------------------------------------------------------------------------
318 // resets the 'check needed' flag (needed, if aborted)
319 //------------------------------------------------------------------------------
320 static void impl_setNeedsCompatCheck()
322 try {
323 Reference< XMultiServiceFactory > theConfigProvider(
324 configuration::theDefaultProvider::get(
325 comphelper::getProcessComponentContext() ) );
327 Sequence< Any > theArgs(1);
328 beans::NamedValue v( OUString("nodepath"),
329 makeAny( OUString("org.openoffice.Setup/Office") ) );
330 theArgs[0] <<= v;
331 Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >(
332 theConfigProvider->createInstanceWithArguments( OUString(aAccessSrvc), theArgs ), UNO_QUERY_THROW );
334 Any value = makeAny( OUString("never") );
336 pset->setPropertyValue( OUString("LastCompatibilityCheckID"), value );
337 Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges();
339 catch (const Exception&) {}
342 //------------------------------------------------------------------------------
343 // to check if we need checking the dependencies of the extensions again, we compare
344 // the build id of the office with the one of the last check
345 //------------------------------------------------------------------------------
346 static bool impl_needsCompatCheck()
348 bool bNeedsCheck = false;
349 OUString aLastCheckBuildID;
350 OUString aCurrentBuildID( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" );
351 rtl::Bootstrap::expandMacros( aCurrentBuildID );
353 try {
354 Reference< XMultiServiceFactory > theConfigProvider(
355 configuration::theDefaultProvider::get(
356 comphelper::getProcessComponentContext() ) );
358 Sequence< Any > theArgs(1);
359 beans::NamedValue v( OUString("nodepath"),
360 makeAny( OUString("org.openoffice.Setup/Office") ) );
361 theArgs[0] <<= v;
362 Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >(
363 theConfigProvider->createInstanceWithArguments( OUString(aAccessSrvc), theArgs ), UNO_QUERY_THROW );
365 Any result = pset->getPropertyValue( OUString("LastCompatibilityCheckID") );
367 result >>= aLastCheckBuildID;
368 if ( aLastCheckBuildID != aCurrentBuildID )
370 bNeedsCheck = true;
371 result <<= aCurrentBuildID;
372 pset->setPropertyValue( OUString("LastCompatibilityCheckID"), result );
373 Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges();
375 #ifdef DEBUG
376 bNeedsCheck = true;
377 #endif
379 catch (const com::sun::star::uno::Exception&) {}
381 return bNeedsCheck;
384 //------------------------------------------------------------------------------
385 // Do we need to check the dependencies of the extensions?
386 // When there are unresolved issues, we can't continue with startup
387 sal_Bool Desktop::CheckExtensionDependencies()
389 if (!impl_needsCompatCheck())
391 return false;
394 uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext();
396 bool bDependenciesValid = impl_checkDependencies( xContext );
398 short nRet = 0;
400 if ( !bDependenciesValid )
401 nRet = impl_showExtensionDialog( xContext );
403 if ( nRet == -1 )
405 impl_setNeedsCompatCheck();
406 return true;
408 else
409 return false;
412 void Desktop::SynchronizeExtensionRepositories()
414 RTL_LOGFILE_CONTEXT(aLog,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories");
415 uno::Reference< uno::XComponentContext > context(
416 comphelper_getProcessComponentContext());
417 uno::Reference< ucb::XCommandEnvironment > silent(
418 new SilentCommandEnv(context, this));
419 if (m_bCleanedExtensionCache) {
420 deployment::ExtensionManager::get(context)->reinstallDeployedExtensions(
421 true, "user", Reference<task::XAbortChannel>(), silent);
422 task::OfficeRestartManager::get(context)->requestRestart(
423 silent->getInteractionHandler());
424 } else {
425 // reinstallDeployedExtensions above already calls syncRepositories
426 // internally:
427 dp_misc::syncRepositories(false, silent);
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */