xref: /trunk/main/desktop/source/pkgchk/unopkg/unopkg_app.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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;
ExtensionName__anon6ed6acfe0111::ExtensionName65     ExtensionName( OUString const & str ) : m_str( str ) {}
operator ()__anon6ed6acfe0111::ExtensionName66     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:
DialogClosedListenerImpl(osl::Condition & rDialogClosedCondition)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)
disposing(lang::EventObject const &)149 void DialogClosedListenerImpl::disposing( lang::EventObject const & )
150 {
151     // nothing to do
152 }
153 
154 // XDialogClosedListener
dialogClosed(ui::dialogs::DialogClosedEvent const &)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.
findPackage(OUString const & repository,Reference<deployment::XExtensionManager> const & manager,Reference<ucb::XCommandEnvironment> const & environment,OUString const & idOrFileName)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
disposeBridges(Reference<css::uno::XComponentContext> ctx)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 //##############################################################################
unopkg_main()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