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 26 #include "dp_misc.h" 27 #include "unopkg_main.h" 28 #include "unopkg_shared.h" 29 #include "dp_identifier.hxx" 30 #include "sal/main.h" 31 #include "tools/extendapplicationenvironment.hxx" 32 #include "rtl/ustrbuf.hxx" 33 #include "rtl/uri.hxx" 34 #include "rtl/bootstrap.hxx" 35 #include "osl/thread.h" 36 #include "osl/process.h" 37 #include "osl/conditn.hxx" 38 #include "osl/file.hxx" 39 #include "cppuhelper/implbase1.hxx" 40 #include "cppuhelper/exc_hlp.hxx" 41 #include "comphelper/anytostring.hxx" 42 #include "comphelper/sequence.hxx" 43 #include "com/sun/star/deployment/ExtensionManager.hpp" 44 45 #include "com/sun/star/deployment/ui/PackageManagerDialog.hpp" 46 #include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" 47 #include "com/sun/star/lang/DisposedException.hpp" 48 #include "boost/scoped_array.hpp" 49 #include "com/sun/star/ui/dialogs/XDialogClosedListener.hpp" 50 #include "com/sun/star/bridge/XBridgeFactory.hpp" 51 #include <stdio.h> 52 #include <vector> 53 54 55 using namespace ::com::sun::star; 56 using namespace ::com::sun::star::uno; 57 using namespace ::unopkg; 58 using ::rtl::OUString; 59 namespace css = ::com::sun::star; 60 namespace { 61 62 struct ExtensionName 63 { 64 OUString m_str; 65 ExtensionName( OUString const & str ) : m_str( str ) {} 66 bool operator () ( Reference<deployment::XPackage> const & e ) const 67 { 68 if (m_str.equals(dp_misc::getIdentifier(e)) 69 || m_str.equals(e->getName())) 70 return true; 71 return false; 72 } 73 }; 74 75 //------------------------------------------------------------------------------ 76 const char s_usingText [] = 77 "\n" 78 "using: " APP_NAME " add <options> extension-path...\n" 79 " " APP_NAME " validate <options> extension-identifier...\n" 80 " " APP_NAME " remove <options> extension-identifier...\n" 81 " " APP_NAME " list <options> extension-identifier...\n" 82 " " APP_NAME " reinstall <options>\n" 83 " " APP_NAME " gui\n" 84 " " APP_NAME " -V\n" 85 " " APP_NAME " -h\n" 86 "\n" 87 "sub-commands:\n" 88 " add add extension\n" 89 " validate checks the prerequisites of an installed extension and" 90 " registers it if possible\n" 91 " remove remove extensions by identifier\n" 92 " reinstall expert feature: reinstall all deployed extensions\n" 93 " list list information about deployed extensions\n" 94 " gui raise Extension Manager Graphical User Interface (GUI)\n" 95 "\n" 96 "options:\n" 97 " -h, --help this help\n" 98 " -V, --version version information\n" 99 " -v, --verbose verbose output to stdout\n" 100 " -f, --force force overwriting existing extensions\n" 101 " -s, --suppress-license prevents showing the license provided that\n" 102 " the extension allows it\n" 103 " --log-file <file> custom log file; default: <cache-dir>/log.txt\n" 104 " --shared expert feature: operate on shared installation\n" 105 " deployment context;\n" 106 " run only when no concurrent Office\n" 107 " process(es) are running!\n" 108 " --bundled expert feature: operate on bundled extensions. Only\n" 109 " works with list, validate, reinstall;\n" 110 " --deployment-context expert feature: explicit deployment context\n" 111 " <context>\n" 112 "\n" 113 "To learn more about the Extension Manager and extensions, see:\n" 114 "https://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Extensions\n\n"; 115 116 //------------------------------------------------------------------------------ 117 const OptionInfo s_option_infos [] = { 118 { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false }, 119 { RTL_CONSTASCII_STRINGPARAM("version"), 'V', false }, 120 { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, 121 { RTL_CONSTASCII_STRINGPARAM("force"), 'f', false }, 122 { RTL_CONSTASCII_STRINGPARAM("log-file"), '\0', true }, 123 { RTL_CONSTASCII_STRINGPARAM("shared"), '\0', false }, 124 { RTL_CONSTASCII_STRINGPARAM("deployment-context"), '\0', true }, 125 { RTL_CONSTASCII_STRINGPARAM("bundled"), '\0', false}, 126 { RTL_CONSTASCII_STRINGPARAM("suppress-license"), 's', false}, 127 128 { 0, 0, '\0', false } 129 }; 130 131 class DialogClosedListenerImpl : 132 public ::cppu::WeakImplHelper1< ui::dialogs::XDialogClosedListener > 133 { 134 osl::Condition & m_rDialogClosedCondition; 135 136 public: 137 DialogClosedListenerImpl( osl::Condition & rDialogClosedCondition ) 138 : m_rDialogClosedCondition( rDialogClosedCondition ) {} 139 140 // XEventListener (base of XDialogClosedListener) 141 virtual void SAL_CALL disposing( lang::EventObject const & Source ); 142 143 // XDialogClosedListener 144 virtual void SAL_CALL dialogClosed( 145 ui::dialogs::DialogClosedEvent const & aEvent ); 146 }; 147 148 // XEventListener (base of XDialogClosedListener) 149 void DialogClosedListenerImpl::disposing( lang::EventObject const & ) 150 { 151 // nothing to do 152 } 153 154 // XDialogClosedListener 155 void DialogClosedListenerImpl::dialogClosed( 156 ui::dialogs::DialogClosedEvent const & ) 157 { 158 m_rDialogClosedCondition.set(); 159 } 160 161 // If a package had been installed with a pre OOo 2.2, it could not normally be 162 // found via its identifier; similarly (and for ease of use), a package 163 // installed with OOo 2.2 or later could not normally be found via its file 164 // name. 165 Reference<deployment::XPackage> findPackage( 166 OUString const & repository, 167 Reference<deployment::XExtensionManager> const & manager, 168 Reference<ucb::XCommandEnvironment > const & environment, 169 OUString const & idOrFileName ) 170 { 171 Sequence< Reference<deployment::XPackage> > ps( 172 manager->getDeployedExtensions(repository, 173 Reference<task::XAbortChannel>(), environment ) ); 174 for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) 175 if ( dp_misc::getIdentifier( ps[i] ) == idOrFileName ) 176 return ps[i]; 177 for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) 178 if ( ps[i]->getName() == idOrFileName ) 179 return ps[i]; 180 return Reference<deployment::XPackage>(); 181 } 182 183 } // anon namespace 184 185 186 //workaround for some reason the bridge threads which communicate with the uno.exe 187 //process are not released on time 188 void disposeBridges(Reference<css::uno::XComponentContext> ctx) 189 { 190 if (!ctx.is()) 191 return; 192 193 Reference<css::bridge::XBridgeFactory> bridgeFac( 194 ctx->getServiceManager()->createInstanceWithContext( 195 OUSTR("com.sun.star.bridge.BridgeFactory"), ctx), 196 UNO_QUERY); 197 198 if (bridgeFac.is()) 199 { 200 const Sequence< Reference<css::bridge::XBridge> >seqBridges = bridgeFac->getExistingBridges(); 201 for (sal_Int32 i = 0; i < seqBridges.getLength(); i++) 202 { 203 Reference<css::lang::XComponent> comp(seqBridges[i], UNO_QUERY); 204 if (comp.is()) 205 { 206 try { 207 comp->dispose(); 208 } 209 catch (css::lang::DisposedException& ) 210 { 211 } 212 } 213 } 214 } 215 } 216 217 //############################################################################## 218 extern "C" int unopkg_main() 219 { 220 tools::extendApplicationEnvironment(); 221 DisposeGuard disposeGuard; 222 bool bNoOtherErrorMsg = false; 223 OUString subCommand; 224 bool option_shared = false; 225 bool option_force = false; 226 bool option_verbose = false; 227 bool option_bundled = false; 228 bool option_suppressLicense = false; 229 bool subcmd_add = false; 230 bool subcmd_gui = false; 231 OUString logFile; 232 OUString repository; 233 OUString cmdArg; 234 ::std::vector<OUString> cmdPackages; 235 236 OptionInfo const * info_shared = getOptionInfo( 237 s_option_infos, OUSTR("shared") ); 238 OptionInfo const * info_force = getOptionInfo( 239 s_option_infos, OUSTR("force") ); 240 OptionInfo const * info_verbose = getOptionInfo( 241 s_option_infos, OUSTR("verbose") ); 242 OptionInfo const * info_log = getOptionInfo( 243 s_option_infos, OUSTR("log-file") ); 244 OptionInfo const * info_context = getOptionInfo( 245 s_option_infos, OUSTR("deployment-context") ); 246 OptionInfo const * info_help = getOptionInfo( 247 s_option_infos, OUSTR("help") ); 248 OptionInfo const * info_version = getOptionInfo( 249 s_option_infos, OUSTR("version") ); 250 OptionInfo const * info_bundled = getOptionInfo( 251 s_option_infos, OUSTR("bundled") ); 252 OptionInfo const * info_suppressLicense = getOptionInfo( 253 s_option_infos, OUSTR("suppress-license") ); 254 255 256 Reference<XComponentContext> xComponentContext; 257 Reference<XComponentContext> xLocalComponentContext; 258 259 try { 260 sal_uInt32 nPos = 0; 261 sal_uInt32 nCount = osl_getCommandArgCount(); 262 if (nCount == 0 || isOption( info_help, &nPos )) 263 { 264 dp_misc::writeConsole(s_usingText); 265 return 0; 266 } 267 else if (isOption( info_version, &nPos )) { 268 dp_misc::writeConsole( "\n" APP_NAME " Version 3.3\n"); 269 return 0; 270 } 271 // consume all bootstrap variables which may occur before the subcommand 272 while(isBootstrapVariable(&nPos)); 273 274 if(nPos >= nCount) 275 return 0; 276 //get the sub command 277 osl_getCommandArg( nPos, &subCommand.pData ); 278 ++nPos; 279 subCommand = subCommand.trim(); 280 subcmd_add = subCommand.equalsAsciiL( 281 RTL_CONSTASCII_STRINGPARAM("add") ); 282 subcmd_gui = subCommand.equalsAsciiL( 283 RTL_CONSTASCII_STRINGPARAM("gui") ); 284 285 // sun-command options and packages: 286 while (nPos < nCount) 287 { 288 if (readArgument( &cmdArg, info_log, &nPos )) { 289 logFile = makeAbsoluteFileUrl( 290 cmdArg.trim(), getProcessWorkingDir() ); 291 } 292 else if (!readOption( &option_verbose, info_verbose, &nPos ) && 293 !readOption( &option_shared, info_shared, &nPos ) && 294 !readOption( &option_force, info_force, &nPos ) && 295 !readOption( &option_bundled, info_bundled, &nPos ) && 296 !readOption( &option_suppressLicense, info_suppressLicense, &nPos ) && 297 !readArgument( &repository, info_context, &nPos ) && 298 !isBootstrapVariable(&nPos)) 299 { 300 osl_getCommandArg( nPos, &cmdArg.pData ); 301 ++nPos; 302 cmdArg = cmdArg.trim(); 303 if (cmdArg.getLength() > 0) 304 { 305 if (cmdArg[ 0 ] == '-') 306 { 307 // is option: 308 dp_misc::writeConsoleError( 309 OUSTR("\nERROR: unexpected option ") + 310 cmdArg + 311 OUSTR("!\n") + 312 OUSTR(" Use " APP_NAME " ") + 313 toString(info_help) + 314 OUSTR(" to print all options.\n")); 315 return 1; 316 } 317 else 318 { 319 // is package: 320 cmdPackages.push_back( 321 subcmd_add || subcmd_gui 322 ? makeAbsoluteFileUrl( 323 cmdArg, getProcessWorkingDir() ) 324 : cmdArg ); 325 } 326 } 327 } 328 } 329 330 if (repository.getLength() == 0) 331 { 332 if (option_shared) 333 repository = OUSTR("shared"); 334 else if (option_bundled) 335 repository = OUSTR("bundled"); 336 else 337 repository = OUSTR("user"); 338 } 339 else 340 { 341 if (repository.equalsAsciiL( 342 RTL_CONSTASCII_STRINGPARAM("shared") )) { 343 option_shared = true; 344 } 345 else if (option_shared) { 346 dp_misc::writeConsoleError( 347 OUSTR("WARNING: explicit context given! ") + 348 OUSTR("Ignoring option ") + 349 toString( info_shared ) + 350 OUSTR("!\n") ); 351 } 352 } 353 354 if (subCommand.equals(OUSTR("reinstall"))) 355 { 356 //We must prevent that services and types are loaded by UNO, 357 //otherwise we cannot delete the registry data folder. 358 OUString extensionUnorc; 359 if (repository.equals(OUSTR("user"))) 360 extensionUnorc = OUSTR("$UNO_USER_PACKAGES_CACHE/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); 361 else if (repository.equals(OUSTR("shared"))) 362 extensionUnorc = OUSTR("$SHARED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); 363 else if (repository.equals(OUSTR("bundled"))) 364 extensionUnorc = OUSTR("$BUNDLED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); 365 else 366 OSL_ASSERT(0); 367 368 ::rtl::Bootstrap::expandMacros(extensionUnorc); 369 oslFileError e = osl_removeFile(extensionUnorc.pData); 370 if (e != osl_File_E_None && e != osl_File_E_NOENT) 371 throw Exception(OUSTR("Could not delete ") + extensionUnorc, 0); 372 } 373 else if (subCommand.equals(OUSTR("sync"))) 374 { 375 //sync is private!!!! Only to be called from setup!!! 376 //The UserInstallation is diverted to the prereg folder. But only 377 //the lock file is written! This requires that 378 //-env:UNO_JAVA_JFW_INSTALL_DATA is passed to javaldx and unopkg otherwise the 379 //javasettings file is written to the prereg folder. 380 // 381 //For performance reasons unopkg sync is called during the setup and 382 //creates the registration data for the repository of the bundled 383 //extensions. It is then copied to the user installation during 384 //startup of AOO (userdata/extensions/bundled). The registration 385 //data is in the brand installation and must be removed when 386 //uninstalling AOO. We do this here, before UNO is 387 //bootstrapped. Otherwise files could be locked by this process. 388 389 //If there is no folder left in 390 //$OOO_BASE_DIR/share/extensions 391 //then we can delete the registration data at 392 //$BUNDLED_EXTENSIONS_USER 393 if (hasNoFolder(OUSTR("$OOO_BASE_DIR/share/extensions"))) 394 { 395 removeFolder(OUSTR("$BUNDLED_EXTENSIONS_PREREG")); 396 //return otherwise we create the registration data again 397 return 0; 398 } 399 //redirect the UserInstallation, so we do not create a 400 //user installation for the admin and we also do not need 401 //to call unopkg with -env:UserInstallation 402 ::rtl::Bootstrap::set(OUSTR("UserInstallation"), 403 OUSTR("$BUNDLED_EXTENSIONS_PREREG/..")); 404 //Setting UNO_JAVA_JFW_INSTALL_DATA causes the javasettings to be written 405 //in the office installation. We do not want to create the user data folder 406 //for the admin. The value must also be set in the unopkg script (Linux, etc.) 407 //when calling javaldx 408 ::rtl::Bootstrap::set(OUSTR("UNO_JAVA_JFW_INSTALL_DATA"), 409 OUSTR("$OOO_BASE_DIR/share/config/javasettingsunopkginstall.xml")); 410 411 } 412 413 xComponentContext = getUNO( 414 disposeGuard, option_verbose, option_shared, subcmd_gui, 415 xLocalComponentContext ); 416 417 Reference<deployment::XExtensionManager> xExtensionManager( 418 deployment::ExtensionManager::get( xComponentContext ) ); 419 420 Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv( 421 createCmdEnv( xComponentContext, logFile, 422 option_force, option_verbose) ); 423 424 //synchronize bundled/shared extensions 425 //Do not synchronize when command is "reinstall". This could add types and services to UNO and 426 //prevent the deletion of the registry data folder 427 //synching is done in XExtensionManager.reinstall 428 if (!subcmd_gui && ! subCommand.equals(OUSTR("reinstall")) 429 && ! subCommand.equals(OUSTR("sync")) 430 && ! dp_misc::office_is_running()) 431 dp_misc::syncRepositories(xCmdEnv); 432 433 if (subcmd_add || 434 subCommand.equalsAsciiL( 435 RTL_CONSTASCII_STRINGPARAM("remove") )) 436 { 437 for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) 438 { 439 OUString const & cmdPackage = cmdPackages[ pos ]; 440 if (subcmd_add) 441 { 442 beans::NamedValue nvSuppress( 443 OUSTR("SUPPRESS_LICENSE"), option_suppressLicense ? 444 makeAny(OUSTR("1")):makeAny(OUSTR("0"))); 445 xExtensionManager->addExtension( 446 cmdPackage, Sequence<beans::NamedValue>(&nvSuppress, 1), 447 repository, Reference<task::XAbortChannel>(), xCmdEnv); 448 } 449 else 450 { 451 try 452 { 453 xExtensionManager->removeExtension( 454 cmdPackage, cmdPackage, repository, 455 Reference<task::XAbortChannel>(), xCmdEnv ); 456 } 457 catch (lang::IllegalArgumentException &) 458 { 459 Reference<deployment::XPackage> p( 460 findPackage(repository, 461 xExtensionManager, xCmdEnv, cmdPackage ) ); 462 if ( !p.is()) 463 throw; 464 else if (p.is()) 465 xExtensionManager->removeExtension( 466 ::dp_misc::getIdentifier(p), p->getName(), 467 repository, 468 Reference<task::XAbortChannel>(), xCmdEnv ); 469 } 470 } 471 } 472 } 473 else if (subCommand.equalsAsciiL( 474 RTL_CONSTASCII_STRINGPARAM("reinstall") )) 475 { 476 xExtensionManager->reinstallDeployedExtensions( 477 repository, Reference<task::XAbortChannel>(), xCmdEnv); 478 } 479 else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("list") )) 480 { 481 ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; 482 ::comphelper::sequenceToContainer(vecExtUnaccepted, 483 xExtensionManager->getExtensionsWithUnacceptedLicenses( 484 repository, xCmdEnv)); 485 486 //This vector tells what XPackage in allExtensions has an 487 //unaccepted license. 488 std::vector<bool> vecUnaccepted; 489 std::vector<Reference<deployment::XPackage> > allExtensions; 490 if (cmdPackages.empty()) 491 { 492 Sequence< Reference<deployment::XPackage> > 493 packages = xExtensionManager->getDeployedExtensions( 494 repository, Reference<task::XAbortChannel>(), xCmdEnv ); 495 496 ::std::vector<Reference<deployment::XPackage> > vec_packages; 497 ::comphelper::sequenceToContainer(vec_packages, packages); 498 499 //First copy the extensions with the unaccepted license 500 //to vector allExtensions. 501 allExtensions.resize(vecExtUnaccepted.size() + vec_packages.size()); 502 503 ::std::vector<Reference<deployment::XPackage> >::iterator i_all_ext = 504 ::std::copy(vecExtUnaccepted.begin(), vecExtUnaccepted.end(), 505 allExtensions.begin()); 506 //Now copy those we got from getDeployedExtensions 507 ::std::copy(vec_packages.begin(), vec_packages.end(), i_all_ext); 508 509 //Now prepare the vector which tells what extension has an 510 //unaccepted license 511 vecUnaccepted.resize(vecExtUnaccepted.size() + vec_packages.size()); 512 ::std::fill_n( vecUnaccepted.begin(), vecExtUnaccepted.size(), true); 513 std::vector<bool>::iterator i_unaccepted = vecUnaccepted.begin() + vecExtUnaccepted.size(); 514 ::std::fill_n(i_unaccepted, vec_packages.size(), false); 515 516 dp_misc::writeConsole( 517 OUSTR("All deployed ") + repository + OUSTR(" extensions:\n\n")); 518 } 519 else 520 { 521 //The user provided the names (ids or file names) of the extensions 522 //which shall be listed 523 for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) 524 { 525 Reference<deployment::XPackage> extension; 526 try 527 { 528 extension = xExtensionManager->getDeployedExtension( 529 repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); 530 } 531 catch (lang::IllegalArgumentException &) 532 { 533 extension = findPackage(repository, 534 xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); 535 } 536 537 //Now look if the requested extension has an unaccepted license 538 bool bUnacceptedLic = false; 539 if (!extension.is()) 540 { 541 ::std::vector<Reference<deployment::XPackage> >::const_iterator 542 i = ::std::find_if( 543 vecExtUnaccepted.begin(), 544 vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); 545 if (i != vecExtUnaccepted.end()) 546 { 547 extension = *i; 548 bUnacceptedLic = true; 549 } 550 } 551 552 if (extension.is()) 553 { 554 allExtensions.push_back(extension); 555 vecUnaccepted.push_back(bUnacceptedLic); 556 } 557 558 else 559 throw lang::IllegalArgumentException( 560 OUSTR("There is no such extension deployed: ") + 561 cmdPackages[pos],0,-1); 562 } 563 564 } 565 566 printf_packages(allExtensions, vecUnaccepted, xCmdEnv ); 567 } 568 else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("validate") )) 569 { 570 ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; 571 ::comphelper::sequenceToContainer( 572 vecExtUnaccepted, xExtensionManager->getExtensionsWithUnacceptedLicenses( 573 repository, xCmdEnv)); 574 575 for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) 576 { 577 Reference<deployment::XPackage> extension; 578 try 579 { 580 extension = xExtensionManager->getDeployedExtension( 581 repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); 582 } 583 catch (lang::IllegalArgumentException &) 584 { 585 extension = findPackage( 586 repository, xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); 587 } 588 589 if (!extension.is()) 590 { 591 ::std::vector<Reference<deployment::XPackage> >::const_iterator 592 i = ::std::find_if( 593 vecExtUnaccepted.begin(), 594 vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); 595 if (i != vecExtUnaccepted.end()) 596 { 597 extension = *i; 598 } 599 } 600 601 if (extension.is()) 602 xExtensionManager->checkPrerequisitesAndEnable( 603 extension, Reference<task::XAbortChannel>(), xCmdEnv); 604 } 605 } 606 else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("gui") )) 607 { 608 Reference<ui::dialogs::XAsynchronousExecutableDialog> xDialog( 609 deployment::ui::PackageManagerDialog::createAndInstall( 610 xComponentContext, 611 cmdPackages.size() > 0 ? cmdPackages[0] : OUString() )); 612 613 osl::Condition dialogEnded; 614 dialogEnded.reset(); 615 616 Reference< ui::dialogs::XDialogClosedListener > xListener( 617 new DialogClosedListenerImpl( dialogEnded ) ); 618 619 xDialog->startExecuteModal(xListener); 620 dialogEnded.wait(); 621 } 622 else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("sync"))) 623 { 624 if (! dp_misc::office_is_running()) 625 { 626 xExtensionManager->synchronizeBundledPrereg( 627 Reference<task::XAbortChannel>(), xCmdEnv); 628 } 629 else 630 { 631 dp_misc::writeConsoleError(OUSTR("\nError: office is running")); 632 } 633 } 634 else 635 { 636 dp_misc::writeConsoleError( 637 OUSTR("\nERROR: unknown sub-command ") + 638 subCommand + 639 OUSTR("!\n") + 640 OUSTR(" Use " APP_NAME " ") + 641 toString(info_help) + 642 OUSTR(" to print all options.\n")); 643 return 1; 644 } 645 646 if (option_verbose) 647 dp_misc::writeConsole( OUSTR( "\n" APP_NAME " done.\n")); 648 //Force to release all bridges which connect us to the child processes 649 disposeBridges(xLocalComponentContext); 650 return 0; 651 } 652 catch (ucb::CommandFailedException &e) 653 { 654 dp_misc::writeConsoleError(e.Message + OUSTR("\n")); 655 bNoOtherErrorMsg = true; 656 } 657 catch (ucb::CommandAbortedException &) 658 { 659 dp_misc::writeConsoleError( "\n" APP_NAME " aborted!\n"); 660 } 661 catch (deployment::DeploymentException & exc) 662 { 663 OUString cause; 664 if (option_verbose) 665 { 666 cause = ::comphelper::anyToString(exc.Cause); 667 } 668 else 669 { 670 css::uno::Exception e; 671 if (exc.Cause >>= e) 672 cause = e.Message; 673 } 674 675 dp_misc::writeConsoleError( 676 OUSTR("\nERROR: ") + exc.Message + OUSTR("\n")); 677 if (cause.getLength()) 678 dp_misc::writeConsoleError( 679 OUSTR(" Cause: ") + cause + OUSTR("\n")); 680 } 681 catch (LockFileException & e) 682 { 683 if (!subcmd_gui) 684 dp_misc::writeConsoleError(e.Message); 685 bNoOtherErrorMsg = true; 686 } 687 catch (::com::sun::star::uno::Exception & e ) { 688 Any exc( ::cppu::getCaughtException() ); 689 690 dp_misc::writeConsoleError( 691 OUSTR("\nERROR: ") + 692 OUString(option_verbose ? e.Message + OUSTR("\nException details: \n") + 693 ::comphelper::anyToString(exc) : e.Message) + 694 OUSTR("\n")); 695 } 696 if (!bNoOtherErrorMsg) 697 dp_misc::writeConsoleError( "\n" APP_NAME " failed.\n"); 698 disposeBridges(xLocalComponentContext); 699 return 1; 700 } 701