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