Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "vcl/svapp.hxx"
30 : : #include "vcl/msgbox.hxx"
31 : :
32 : : #include "osl/mutex.hxx"
33 : :
34 : : #include "toolkit/helper/vclunohelper.hxx"
35 : :
36 : : #include "com/sun/star/beans/XPropertySet.hpp"
37 : : #include "com/sun/star/configuration/theDefaultProvider.hpp"
38 : :
39 : : #include "dp_gui_dialog2.hxx"
40 : : #include "dp_gui_extensioncmdqueue.hxx"
41 : : #include "dp_gui_theextmgr.hxx"
42 : : #include "dp_identifier.hxx"
43 : : #include "dp_update.hxx"
44 : :
45 : : #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
46 : :
47 : : #define USER_PACKAGE_MANAGER OUSTR("user")
48 : : #define SHARED_PACKAGE_MANAGER OUSTR("shared")
49 : : #define BUNDLED_PACKAGE_MANAGER OUSTR("bundled")
50 : :
51 : : using namespace ::com::sun::star;
52 : : using ::rtl::OUString;
53 : :
54 : : namespace dp_gui {
55 : :
56 : : //------------------------------------------------------------------------------
57 : :
58 : 0 : ::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr;
59 : :
60 : : //------------------------------------------------------------------------------
61 : : // TheExtensionManager
62 : : //------------------------------------------------------------------------------
63 : :
64 : 0 : TheExtensionManager::TheExtensionManager( Window *pParent,
65 : : const uno::Reference< uno::XComponentContext > &xContext ) :
66 : : m_xContext( xContext ),
67 : : m_pParent( pParent ),
68 : : m_pExtMgrDialog( NULL ),
69 : : m_pUpdReqDialog( NULL ),
70 : 0 : m_pExecuteCmdQueue( NULL )
71 : : {
72 : 0 : m_xExtensionManager = deployment::ExtensionManager::get( xContext );
73 : 0 : m_xExtensionManager->addModifyListener( this );
74 : :
75 : : uno::Reference< lang::XMultiServiceFactory > xConfig(
76 : 0 : configuration::theDefaultProvider::get(xContext));
77 : 0 : uno::Any args[1];
78 : : beans::PropertyValue aValue( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.OptionsDialog/Nodes") ),
79 : 0 : beans::PropertyState_DIRECT_VALUE );
80 : 0 : args[0] <<= aValue;
81 : : m_xNameAccessNodes = uno::Reference< container::XNameAccess >(
82 : 0 : xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"),
83 : 0 : uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW);
84 : :
85 : : // get the 'get more extensions here' url
86 : 0 : uno::Reference< container::XNameAccess > xNameAccessRepositories;
87 : : beans::PropertyValue aValue2( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionRepositories") ),
88 : 0 : beans::PropertyState_DIRECT_VALUE );
89 : 0 : args[0] <<= aValue2;
90 : : xNameAccessRepositories = uno::Reference< container::XNameAccess > (
91 : 0 : xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"),
92 : 0 : uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW);
93 : : try
94 : : { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
95 : 0 : uno::Any value = xNameAccessRepositories->getByName( OUSTR( "WebsiteLink" ) );
96 : 0 : m_sGetExtensionsURL = value.get< OUString > ();
97 : : }
98 : 0 : catch ( const uno::Exception& )
99 : : {}
100 : :
101 : 0 : if ( dp_misc::office_is_running() )
102 : : {
103 : : // the registration should be done after the construction has been ended
104 : : // otherwise an exception prevents object creation, but it is registered as a listener
105 : 0 : m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext(
106 : 0 : OUSTR("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY );
107 : 0 : if ( m_xDesktop.is() )
108 : 0 : m_xDesktop->addTerminateListener( this );
109 : 0 : }
110 : 0 : }
111 : :
112 : : //------------------------------------------------------------------------------
113 : 0 : TheExtensionManager::~TheExtensionManager()
114 : : {
115 : 0 : if ( m_pUpdReqDialog )
116 : 0 : delete m_pUpdReqDialog;
117 : 0 : if ( m_pExtMgrDialog )
118 : 0 : delete m_pExtMgrDialog;
119 : 0 : if ( m_pExecuteCmdQueue )
120 : 0 : delete m_pExecuteCmdQueue;
121 : 0 : }
122 : :
123 : : //------------------------------------------------------------------------------
124 : 0 : void TheExtensionManager::createDialog( const bool bCreateUpdDlg )
125 : : {
126 : 0 : const SolarMutexGuard guard;
127 : :
128 : 0 : if ( bCreateUpdDlg )
129 : : {
130 : 0 : if ( !m_pUpdReqDialog )
131 : : {
132 : 0 : m_pUpdReqDialog = new UpdateRequiredDialog( NULL, this );
133 : 0 : delete m_pExecuteCmdQueue;
134 : 0 : m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pUpdReqDialog, this, m_xContext );
135 : 0 : createPackageList();
136 : : }
137 : : }
138 : 0 : else if ( !m_pExtMgrDialog )
139 : : {
140 : 0 : m_pExtMgrDialog = new ExtMgrDialog( m_pParent, this );
141 : 0 : delete m_pExecuteCmdQueue;
142 : 0 : m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pExtMgrDialog, this, m_xContext );
143 : 0 : m_pExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL );
144 : 0 : createPackageList();
145 : 0 : }
146 : 0 : }
147 : :
148 : : //------------------------------------------------------------------------------
149 : 0 : void TheExtensionManager::Show()
150 : : {
151 : 0 : const SolarMutexGuard guard;
152 : :
153 : 0 : getDialog()->Show();
154 : 0 : }
155 : :
156 : : //------------------------------------------------------------------------------
157 : 0 : void TheExtensionManager::SetText( const ::rtl::OUString &rTitle )
158 : : {
159 : 0 : const SolarMutexGuard guard;
160 : :
161 : 0 : getDialog()->SetText( rTitle );
162 : 0 : }
163 : :
164 : : //------------------------------------------------------------------------------
165 : 0 : void TheExtensionManager::ToTop( sal_uInt16 nFlags )
166 : : {
167 : 0 : const SolarMutexGuard guard;
168 : :
169 : 0 : getDialog()->ToTop( nFlags );
170 : 0 : }
171 : :
172 : : //------------------------------------------------------------------------------
173 : 0 : bool TheExtensionManager::Close()
174 : : {
175 : 0 : if ( m_pExtMgrDialog )
176 : 0 : return m_pExtMgrDialog->Close();
177 : 0 : else if ( m_pUpdReqDialog )
178 : 0 : return m_pUpdReqDialog->Close();
179 : : else
180 : 0 : return true;
181 : : }
182 : :
183 : : //------------------------------------------------------------------------------
184 : 0 : sal_Int16 TheExtensionManager::execute()
185 : : {
186 : 0 : sal_Int16 nRet = 0;
187 : :
188 : 0 : if ( m_pUpdReqDialog )
189 : : {
190 : 0 : nRet = m_pUpdReqDialog->Execute();
191 : 0 : delete m_pUpdReqDialog;
192 : 0 : m_pUpdReqDialog = NULL;
193 : : }
194 : :
195 : 0 : return nRet;
196 : : }
197 : :
198 : : //------------------------------------------------------------------------------
199 : 0 : bool TheExtensionManager::isVisible()
200 : : {
201 : 0 : return getDialog()->IsVisible();
202 : : }
203 : :
204 : : //------------------------------------------------------------------------------
205 : 0 : bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ )
206 : : {
207 : 0 : std::vector< uno::Reference< deployment::XPackage > > vEntries;
208 : 0 : uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
209 : :
210 : : try {
211 : 0 : xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
212 : 0 : uno::Reference< ucb::XCommandEnvironment >() );
213 : 0 : } catch ( const deployment::DeploymentException & ) {
214 : 0 : return false;
215 : 0 : } catch ( const ucb::CommandFailedException & ) {
216 : 0 : return false;
217 : 0 : } catch ( const ucb::CommandAbortedException & ) {
218 : 0 : return false;
219 : 0 : } catch ( const lang::IllegalArgumentException & e ) {
220 : 0 : throw uno::RuntimeException( e.Message, e.Context );
221 : : }
222 : :
223 : 0 : for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
224 : : {
225 : 0 : uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]);
226 : : OSL_ASSERT(xPackage.is());
227 : 0 : if ( xPackage.is() )
228 : : {
229 : 0 : vEntries.push_back( xPackage );
230 : : }
231 : 0 : }
232 : :
233 : 0 : m_pExecuteCmdQueue->checkForUpdates( vEntries );
234 : 0 : return true;
235 : : }
236 : :
237 : : //------------------------------------------------------------------------------
238 : 0 : bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser )
239 : : {
240 : 0 : if ( rPackageURL.isEmpty() )
241 : 0 : return false;
242 : :
243 : 0 : createDialog( false );
244 : :
245 : 0 : bool bInstall = true;
246 : 0 : bool bInstallForAll = false;
247 : :
248 : : // DV! missing function is read only repository from extension manager
249 : 0 : if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) )
250 : 0 : bInstall = getDialogHelper()->installForAllUsers( bInstallForAll );
251 : :
252 : 0 : if ( !bInstall )
253 : 0 : return false;
254 : :
255 : 0 : if ( bInstallForAll )
256 : 0 : m_pExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false );
257 : : else
258 : 0 : m_pExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser );
259 : :
260 : 0 : return true;
261 : : }
262 : :
263 : : //------------------------------------------------------------------------------
264 : 0 : bool TheExtensionManager::queryTermination()
265 : : {
266 : 0 : if ( dp_misc::office_is_running() )
267 : 0 : return true;
268 : : // the standalone application unopkg must not close ( and quit ) the dialog
269 : : // when there are still actions in the queue
270 : 0 : return true;
271 : : }
272 : :
273 : : //------------------------------------------------------------------------------
274 : 0 : void TheExtensionManager::terminateDialog()
275 : : {
276 : 0 : if ( ! dp_misc::office_is_running() )
277 : : {
278 : 0 : const SolarMutexGuard guard;
279 : 0 : delete m_pExtMgrDialog;
280 : 0 : m_pExtMgrDialog = NULL;
281 : 0 : delete m_pUpdReqDialog;
282 : 0 : m_pUpdReqDialog = NULL;
283 : 0 : Application::Quit();
284 : : }
285 : 0 : }
286 : :
287 : : //------------------------------------------------------------------------------
288 : 0 : void TheExtensionManager::createPackageList()
289 : : {
290 : 0 : uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
291 : :
292 : : try {
293 : 0 : xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
294 : 0 : uno::Reference< ucb::XCommandEnvironment >() );
295 : 0 : } catch ( const deployment::DeploymentException & ) {
296 : : return;
297 : 0 : } catch ( const ucb::CommandFailedException & ) {
298 : : return;
299 : 0 : } catch ( const ucb::CommandAbortedException & ) {
300 : : return;
301 : 0 : } catch ( const lang::IllegalArgumentException & e ) {
302 : 0 : throw uno::RuntimeException( e.Message, e.Context );
303 : : }
304 : :
305 : 0 : for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
306 : : {
307 : 0 : uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
308 : :
309 : 0 : for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j )
310 : : {
311 : 0 : uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
312 : 0 : if ( xPackage.is() )
313 : : {
314 : 0 : PackageState eState = getPackageState( xPackage );
315 : 0 : getDialogHelper()->addPackageToList( xPackage );
316 : : // When the package is enabled, we can stop here, otherwise we have to look for
317 : : // another version of this package
318 : 0 : if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) )
319 : : break;
320 : : }
321 : 0 : }
322 : 0 : }
323 : :
324 : 0 : uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages;
325 : 0 : xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER,
326 : 0 : uno::Reference< ucb::XCommandEnvironment >() );
327 : 0 : for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i )
328 : : {
329 : 0 : uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i];
330 : 0 : if ( xPackage.is() )
331 : : {
332 : 0 : getDialogHelper()->addPackageToList( xPackage, true );
333 : : }
334 : 0 : }
335 : : }
336 : :
337 : : //------------------------------------------------------------------------------
338 : 0 : PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage ) const
339 : : {
340 : : try {
341 : : beans::Optional< beans::Ambiguous< sal_Bool > > option(
342 : 0 : xPackage->isRegistered( uno::Reference< task::XAbortChannel >(),
343 : 0 : uno::Reference< ucb::XCommandEnvironment >() ) );
344 : 0 : if ( option.IsPresent )
345 : : {
346 : 0 : ::beans::Ambiguous< sal_Bool > const & reg = option.Value;
347 : 0 : if ( reg.IsAmbiguous )
348 : 0 : return AMBIGUOUS;
349 : : else
350 : 0 : return reg.Value ? REGISTERED : NOT_REGISTERED;
351 : : }
352 : : else
353 : 0 : return NOT_AVAILABLE;
354 : : }
355 : 0 : catch ( const uno::RuntimeException & ) {
356 : 0 : throw;
357 : : }
358 : 0 : catch (const uno::Exception & exc) {
359 : : (void) exc;
360 : : OSL_FAIL( ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
361 : 0 : return NOT_AVAILABLE;
362 : : }
363 : : }
364 : :
365 : : //------------------------------------------------------------------------------
366 : 0 : bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const
367 : : {
368 : 0 : if ( m_xExtensionManager.is() && xPackage.is() )
369 : : {
370 : 0 : return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() );
371 : : }
372 : : else
373 : 0 : return true;
374 : : }
375 : :
376 : : //------------------------------------------------------------------------------
377 : : // The function investigates if the extension supports options.
378 : 0 : bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const
379 : : {
380 : 0 : bool bOptions = false;
381 : :
382 : 0 : if ( ! xPackage->isBundle() )
383 : 0 : return false;
384 : :
385 : 0 : beans::Optional< OUString > aId = xPackage->getIdentifier();
386 : :
387 : : //a bundle must always have an id
388 : : OSL_ASSERT( aId.IsPresent );
389 : :
390 : : //iterate over all available nodes
391 : 0 : uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames();
392 : :
393 : 0 : for ( int i = 0; i < seqNames.getLength(); i++ )
394 : : {
395 : 0 : uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] );
396 : : //If we have a node then then it must contain the set of leaves. This is part of OptionsDialog.xcs
397 : 0 : uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >();
398 : 0 : uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW );
399 : :
400 : 0 : uno::Any anyLeaves = xNode->getByName( OUSTR("Leaves") );
401 : 0 : uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >();
402 : 0 : uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW );
403 : :
404 : : //iterate over all available leaves
405 : 0 : uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames();
406 : 0 : for ( int j = 0; j < seqLeafNames.getLength(); j++ )
407 : : {
408 : 0 : uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] );
409 : 0 : uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >();
410 : 0 : uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW );
411 : : //investigate the Id property if it matches the extension identifier which
412 : : //has been passed in.
413 : 0 : uno::Any anyValue = xLeaf->getPropertyValue( OUSTR("Id") );
414 : :
415 : 0 : OUString sId = anyValue.get< OUString >();
416 : 0 : if ( sId == aId.Value )
417 : : {
418 : 0 : bOptions = true;
419 : : break;
420 : : }
421 : 0 : }
422 : 0 : if ( bOptions )
423 : : break;
424 : 0 : }
425 : 0 : return bOptions;
426 : : }
427 : :
428 : : //------------------------------------------------------------------------------
429 : : // XEventListener
430 : 0 : void TheExtensionManager::disposing( lang::EventObject const & rEvt )
431 : : throw ( uno::RuntimeException )
432 : : {
433 : 0 : bool shutDown = (rEvt.Source == m_xDesktop);
434 : :
435 : 0 : if ( shutDown && m_xDesktop.is() )
436 : : {
437 : 0 : m_xDesktop->removeTerminateListener( this );
438 : 0 : m_xDesktop.clear();
439 : : }
440 : :
441 : 0 : if ( shutDown )
442 : : {
443 : 0 : if ( dp_misc::office_is_running() )
444 : : {
445 : 0 : const SolarMutexGuard guard;
446 : 0 : delete m_pExtMgrDialog;
447 : 0 : m_pExtMgrDialog = NULL;
448 : 0 : delete m_pUpdReqDialog;
449 : 0 : m_pUpdReqDialog = NULL;
450 : : }
451 : 0 : s_ExtMgr.clear();
452 : : }
453 : 0 : }
454 : :
455 : : //------------------------------------------------------------------------------
456 : : // XTerminateListener
457 : 0 : void TheExtensionManager::queryTermination( ::lang::EventObject const & )
458 : : throw ( frame::TerminationVetoException, uno::RuntimeException )
459 : : {
460 : 0 : DialogHelper *pDialogHelper = getDialogHelper();
461 : :
462 : 0 : if ( m_pExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) )
463 : : {
464 : 0 : ToTop( TOTOP_RESTOREWHENMIN );
465 : : throw frame::TerminationVetoException(
466 : : OUSTR("The office cannot be closed while the Extension Manager is running"),
467 : 0 : uno::Reference<XInterface>(static_cast<frame::XTerminateListener*>(this), uno::UNO_QUERY));
468 : : }
469 : : else
470 : : {
471 : 0 : if ( m_pExtMgrDialog )
472 : 0 : m_pExtMgrDialog->Close();
473 : 0 : if ( m_pUpdReqDialog )
474 : 0 : m_pUpdReqDialog->Close();
475 : : }
476 : 0 : }
477 : :
478 : : //------------------------------------------------------------------------------
479 : 0 : void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt )
480 : : throw ( uno::RuntimeException )
481 : : {
482 : 0 : disposing( rEvt );
483 : 0 : }
484 : :
485 : : //------------------------------------------------------------------------------
486 : : // XModifyListener
487 : 0 : void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ )
488 : : throw ( uno::RuntimeException )
489 : : {
490 : 0 : getDialogHelper()->prepareChecking();
491 : 0 : createPackageList();
492 : 0 : getDialogHelper()->checkEntries();
493 : 0 : }
494 : :
495 : : //------------------------------------------------------------------------------
496 : 0 : ::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext,
497 : : const uno::Reference< awt::XWindow > &xParent,
498 : : const OUString & extensionURL )
499 : : {
500 : 0 : if ( s_ExtMgr.is() )
501 : : {
502 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
503 : 0 : if ( !extensionURL.isEmpty() )
504 : 0 : s_ExtMgr->installPackage( extensionURL, true );
505 : 0 : return s_ExtMgr;
506 : : }
507 : :
508 : 0 : Window * pParent = DIALOG_NO_PARENT;
509 : 0 : if ( xParent.is() )
510 : 0 : pParent = VCLUnoHelper::GetWindow(xParent);
511 : :
512 : 0 : ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( pParent, xContext ) );
513 : :
514 : 0 : const SolarMutexGuard guard;
515 : 0 : if ( ! s_ExtMgr.is() )
516 : : {
517 : : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
518 : 0 : s_ExtMgr = that;
519 : : }
520 : :
521 : 0 : if ( !extensionURL.isEmpty() )
522 : 0 : s_ExtMgr->installPackage( extensionURL, true );
523 : :
524 : 0 : return s_ExtMgr;
525 : : }
526 : :
527 : 0 : } //namespace dp_gui
528 : :
529 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|