Update ooo320-m1
[ooovba.git] / desktop / source / pkgchk / unopkg / unopkg_misc.cxx
blob3518b3fb1e3735ac636a703b7c4b2f06fe98aa80
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unopkg_misc.cxx,v $
10 * $Revision: 1.15.52.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
34 #include "deployment.hrc"
35 #include "unopkg_shared.h"
36 #include "dp_identifier.hxx"
37 #include "../../deployment/gui/dp_gui.hrc"
38 #include "../../app/lockfile.hxx"
39 #include "vcl/svapp.hxx"
40 #include "vcl/msgbox.hxx"
41 #include "rtl/bootstrap.hxx"
42 #include "rtl/strbuf.hxx"
43 #include "rtl/ustrbuf.hxx"
44 #include "osl/process.h"
45 #include "osl/file.hxx"
46 #include "osl/thread.hxx"
47 #include "tools/getprocessworkingdir.hxx"
48 #include "ucbhelper/contentbroker.hxx"
49 #include "ucbhelper/configurationkeys.hxx"
50 #include "unotools/processfactory.hxx"
51 #include "unotools/configmgr.hxx"
52 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
53 #include "cppuhelper/bootstrap.hxx"
54 #include <stdio.h>
56 using ::rtl::OUString;
57 using ::rtl::OString;
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::ucb;
62 namespace unopkg {
64 bool getLockFilePath(OUString & out);
66 ::rtl::OUString toString( OptionInfo const * info )
68 OSL_ASSERT( info != 0 );
69 ::rtl::OUStringBuffer buf;
70 buf.appendAscii("--");
71 buf.appendAscii(info->m_name);
72 if (info->m_short_option != '\0')
74 buf.appendAscii(" (short -" );
75 buf.append(info->m_short_option );
76 buf.appendAscii(")");
78 if (info->m_has_argument)
79 buf.appendAscii(" <argument>" );
80 return buf.makeStringAndClear();
83 //==============================================================================
84 OptionInfo const * getOptionInfo(
85 OptionInfo const * list,
86 OUString const & opt, sal_Unicode copt )
88 for ( ; list->m_name != 0; ++list )
90 OptionInfo const & option_info = *list;
91 if (opt.getLength() > 0)
93 if (opt.equalsAsciiL(
94 option_info.m_name, option_info.m_name_length ) &&
95 (copt == '\0' || copt == option_info.m_short_option))
97 return &option_info;
100 else
102 OSL_ASSERT( copt != '\0' );
103 if (copt == option_info.m_short_option)
105 return &option_info;
109 OSL_ENSURE( 0, ::rtl::OUStringToOString(
110 opt, osl_getThreadTextEncoding() ).getStr() );
111 return 0;
114 //==============================================================================
115 bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex )
117 OSL_ASSERT( option_info != 0 );
118 if (osl_getCommandArgCount() <= *pIndex)
119 return false;
121 OUString arg;
122 osl_getCommandArg( *pIndex, &arg.pData );
123 sal_Int32 len = arg.getLength();
125 if (len < 2 || arg[ 0 ] != '-')
126 return false;
128 if (len == 2 && arg[ 1 ] == option_info->m_short_option)
130 ++(*pIndex);
131 dp_misc::TRACE(OUSTR(__FILE__": identified option \'")
132 + OUSTR("\'") + OUString( option_info->m_short_option ) + OUSTR("\n"));
133 return true;
135 if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
136 arg.pData->buffer + 2, option_info->m_name ) == 0)
138 ++(*pIndex);
139 dp_misc::TRACE(OUSTR( __FILE__": identified option \'")
140 + OUString::createFromAscii(option_info->m_name) + OUSTR("\'\n"));
141 return true;
143 return false;
145 //==============================================================================
147 bool isBootstrapVariable(sal_uInt32 * pIndex)
149 OSL_ASSERT(osl_getCommandArgCount() >= *pIndex);
151 OUString arg;
152 osl_getCommandArg(*pIndex, &arg.pData);
153 if (arg.matchAsciiL("-env:", 5))
155 ++(*pIndex);
156 return true;
158 return false;
161 //==============================================================================
162 bool readArgument(
163 OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
165 if (isOption( option_info, pIndex ))
167 if (*pIndex < osl_getCommandArgCount())
169 OSL_ASSERT( pValue != 0 );
170 osl_getCommandArg( *pIndex, &pValue->pData );
171 dp_misc::TRACE(OUSTR( __FILE__": argument value: ")
172 + *pValue + OUSTR("\n"));
173 ++(*pIndex);
174 return true;
176 --(*pIndex);
178 return false;
181 //##############################################################################
183 namespace {
184 struct ExecutableDir : public rtl::StaticWithInit<
185 const OUString, ExecutableDir> {
186 const OUString operator () () {
187 OUString path;
188 if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) {
189 throw RuntimeException(
190 OUSTR("cannot locate executable directory!"),0 );
192 return path.copy( 0, path.lastIndexOf( '/' ) );
195 struct ProcessWorkingDir : public rtl::StaticWithInit<
196 const OUString, ProcessWorkingDir> {
197 const OUString operator () () {
198 OUString workingDir;
199 tools::getProcessWorkingDir(&workingDir);
200 return workingDir;
203 } // anon namespace
205 //==============================================================================
206 OUString const & getExecutableDir()
208 return ExecutableDir::get();
211 //==============================================================================
212 OUString const & getProcessWorkingDir()
214 return ProcessWorkingDir::get();
217 //==============================================================================
218 OUString makeAbsoluteFileUrl(
219 OUString const & sys_path, OUString const & base_url, bool throw_exc )
221 // system path to file url
222 OUString file_url;
223 oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData );
224 if ( rc != osl_File_E_None) {
225 OUString tempPath;
226 if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) == osl_File_E_None )
228 file_url = sys_path;
230 else if (throw_exc)
232 throw RuntimeException(
233 OUSTR("cannot get file url from system path: ") +
234 sys_path, Reference< XInterface >() );
238 OUString abs;
239 if (osl_getAbsoluteFileURL(
240 base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None)
242 if (throw_exc) {
243 ::rtl::OUStringBuffer buf;
244 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
245 "making absolute file url failed: \"") );
246 buf.append( base_url );
247 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
248 "\" (base-url) and \"") );
249 buf.append( file_url );
250 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" (file-url)!") );
251 throw RuntimeException(
252 buf.makeStringAndClear(), Reference< XInterface >() );
254 return OUString();
256 return abs[ abs.getLength() -1 ] == '/'
257 ? abs.copy( 0, abs.getLength() -1 ) : abs;
260 //##############################################################################
262 namespace {
264 //------------------------------------------------------------------------------
265 inline void printf_space( sal_Int32 space )
267 while (space--)
268 dp_misc::writeConsole(" ");
271 //------------------------------------------------------------------------------
272 void printf_line(
273 OUString const & name, OUString const & value, sal_Int32 level )
275 printf_space( level );
276 dp_misc::writeConsole(name + OUSTR(": ") + value + OUSTR("\n"));
279 //------------------------------------------------------------------------------
280 void printf_package(
281 Reference<deployment::XPackage> const & xPackage,
282 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
284 beans::Optional< OUString > id(
285 level == 0
286 ? beans::Optional< OUString >(
287 true, dp_misc::getIdentifier( xPackage ) )
288 : xPackage->getIdentifier() );
289 if (id.IsPresent)
290 printf_line( OUSTR("Identifier"), id.Value, level );
291 OUString version(xPackage->getVersion());
292 if (version.getLength() != 0)
293 printf_line( OUSTR("Version"), version, level + 1 );
294 printf_line( OUSTR("URL"), xPackage->getURL(), level + 1 );
296 beans::Optional< beans::Ambiguous<sal_Bool> > option(
297 xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) );
298 OUString value;
299 if (option.IsPresent) {
300 beans::Ambiguous<sal_Bool> const & reg = option.Value;
301 if (reg.IsAmbiguous)
302 value = OUSTR("unknown");
303 else
304 value = reg.Value ? OUSTR("yes") : OUSTR("no");
306 else
307 value = OUSTR("n/a");
308 printf_line( OUSTR("is registered"), value, level + 1 );
310 const Reference<deployment::XPackageTypeInfo> xPackageType(
311 xPackage->getPackageType() );
312 OSL_ASSERT( xPackageType.is() );
313 if (xPackageType.is()) {
314 printf_line( OUSTR("Media-Type"),
315 xPackageType->getMediaType(), level + 1 );
317 printf_line( OUSTR("Description"), xPackage->getDescription(), level + 1 );
318 if (xPackage->isBundle()) {
319 Sequence< Reference<deployment::XPackage> > seq(
320 xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) );
321 printf_space( level + 1 );
322 dp_misc::writeConsole("bundled Packages: {\n");
323 printf_packages( seq, xCmdEnv, level + 2 );
324 printf_space( level + 1 );
325 dp_misc::writeConsole("}\n");
329 } // anon namespace
331 //==============================================================================
332 void printf_packages(
333 Sequence< Reference<deployment::XPackage> > const & seq,
334 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
336 sal_Int32 len = seq.getLength();
337 Reference< deployment::XPackage > const * p = seq.getConstArray();
338 if (len == 0) {
339 printf_space( level );
340 dp_misc::writeConsole("<none>\n");
342 else {
343 for ( sal_Int32 pos = 0; pos < len; ++pos )
344 printf_package( p[ pos ], xCmdEnv, level );
348 //##############################################################################
350 namespace {
352 //------------------------------------------------------------------------------
353 Reference<XComponentContext> bootstrapStandAlone(
354 DisposeGuard & disposeGuard, bool /*verbose */)
356 Reference<XComponentContext> xContext =
357 ::cppu::defaultBootstrap_InitialComponentContext();
359 // assure disposing of local component context:
360 disposeGuard.reset(
361 Reference<lang::XComponent>( xContext, UNO_QUERY ) );
363 Reference<lang::XMultiServiceFactory> xServiceManager(
364 xContext->getServiceManager(), UNO_QUERY_THROW );
365 // set global process service factory used by unotools config helpers
366 ::utl::setProcessServiceFactory( xServiceManager );
368 // initialize the ucbhelper ucb,
369 // because the package implementation uses it
370 Sequence<Any> ucb_args( 2 );
371 ucb_args[ 0 ] <<= OUSTR(UCB_CONFIGURATION_KEY1_LOCAL);
372 ucb_args[ 1 ] <<= OUSTR(UCB_CONFIGURATION_KEY2_OFFICE);
373 if (! ::ucbhelper::ContentBroker::initialize( xServiceManager, ucb_args ))
374 throw RuntimeException( OUSTR("cannot initialize UCB!"), 0 );
376 return xContext;
379 //------------------------------------------------------------------------------
380 Reference<XComponentContext> connectToOffice(
381 Reference<XComponentContext> const & xLocalComponentContext,
382 bool verbose )
384 Sequence<OUString> args( 3 );
385 args[ 0 ] = OUSTR("-nologo");
386 args[ 1 ] = OUSTR("-nodefault");
388 OUString pipeId( ::dp_misc::generateRandomPipeId() );
389 ::rtl::OUStringBuffer buf;
390 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("-accept=pipe,name=") );
391 buf.append( pipeId );
392 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(";urp;") );
393 args[ 2 ] = buf.makeStringAndClear();
394 OUString appURL( getExecutableDir() + OUSTR("/soffice") );
396 if (verbose)
398 dp_misc::writeConsole(
399 OUSTR("Raising process: ") +
400 appURL +
401 OUSTR("\nArguments: -nologo -nodefault ") +
402 args[2] +
403 OUSTR("\n"));
406 ::dp_misc::raiseProcess( appURL, args );
408 if (verbose)
409 dp_misc::writeConsole("Ok. Connecting...");
411 OSL_ASSERT( buf.getLength() == 0 );
412 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") );
413 buf.append( pipeId );
414 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
415 ";urp;StarOffice.ComponentContext") );
416 Reference<XComponentContext> xRet(
417 ::dp_misc::resolveUnoURL(
418 buf.makeStringAndClear(), xLocalComponentContext ),
419 UNO_QUERY_THROW );
420 if (verbose)
421 dp_misc::writeConsole("Ok.\n");
423 return xRet;
426 } // anon namespace
428 /** returns the path to the lock file used by unopkg.
429 @return the path. An empty string signifies an error.
431 OUString getLockFilePath()
433 OUString ret;
434 OUString sBootstrap(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}"));
435 rtl::Bootstrap::expandMacros(sBootstrap);
436 OUString sAbs;
437 if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL(
438 sBootstrap, OUSTR(".lock"), sAbs))
440 if (::osl::File::E_None ==
441 ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap))
443 ret = sBootstrap;
447 return ret;
449 //==============================================================================
450 Reference<XComponentContext> getUNO(
451 DisposeGuard & disposeGuard, bool verbose, bool shared, bool bGui,
452 Reference<XComponentContext> & out_localContext)
454 // do not create any user data (for the root user) in --shared mode:
455 if (shared) {
456 rtl::Bootstrap::set(
457 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CFG_CacheUrl")),
458 rtl::OUString());
461 // hold lock during process runtime:
462 static ::desktop::Lockfile s_lockfile( false /* no IPC server */ );
463 Reference<XComponentContext> xComponentContext(
464 bootstrapStandAlone( disposeGuard, verbose ) );
465 out_localContext = xComponentContext;
466 if (::dp_misc::office_is_running()) {
467 xComponentContext.set(
468 connectToOffice( xComponentContext, verbose ) );
470 else
472 if (! s_lockfile.check( 0 ))
474 String sMsg(ResId(RID_STR_CONCURRENTINSTANCE, *DeploymentResMgr::get()));
475 //Create this string before we call DeInitVCL, because this will kill
476 //the ResMgr
477 String sError(ResId(RID_STR_UNOPKG_ERROR, *DeploymentResMgr::get()));
479 sMsg = sMsg + OUSTR("\n") + getLockFilePath();
481 if (bGui)
483 //We show a message box or print to the console that there
484 //is another instance already running
485 if ( ! InitVCL( Reference<lang::XMultiServiceFactory>(
486 xComponentContext->getServiceManager(),
487 UNO_QUERY_THROW ) ))
488 throw RuntimeException( OUSTR("Cannot initialize VCL!"),
489 NULL );
491 WarningBox warn(NULL, WB_OK | WB_DEF_OK, sMsg);
492 warn.SetText(::utl::ConfigManager::GetDirectConfigProperty(
493 ::utl::ConfigManager::PRODUCTNAME).get<OUString>());
494 warn.SetIcon(0);
495 warn.Execute();
497 DeInitVCL();
500 throw LockFileException(
501 OUSTR("\n") + sError + sMsg + OUSTR("\n"));
505 return xComponentContext;