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