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