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