1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
56 using ::rtl::OUString
;
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::ucb
;
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
);
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)
94 option_info
.m_name
, option_info
.m_name_length
) &&
95 (copt
== '\0' || copt
== option_info
.m_short_option
))
102 OSL_ASSERT( copt
!= '\0' );
103 if (copt
== option_info
.m_short_option
)
109 OSL_ENSURE( 0, ::rtl::OUStringToOString(
110 opt
, osl_getThreadTextEncoding() ).getStr() );
114 //==============================================================================
115 bool isOption( OptionInfo
const * option_info
, sal_uInt32
* pIndex
)
117 OSL_ASSERT( option_info
!= 0 );
118 if (osl_getCommandArgCount() <= *pIndex
)
122 osl_getCommandArg( *pIndex
, &arg
.pData
);
123 sal_Int32 len
= arg
.getLength();
125 if (len
< 2 || arg
[ 0 ] != '-')
128 if (len
== 2 && arg
[ 1 ] == option_info
->m_short_option
)
131 dp_misc::TRACE(OUSTR(__FILE__
": identified option \'")
132 + OUSTR("\'") + OUString( option_info
->m_short_option
) + OUSTR("\n"));
135 if (arg
[ 1 ] == '-' && rtl_ustr_ascii_compare(
136 arg
.pData
->buffer
+ 2, option_info
->m_name
) == 0)
139 dp_misc::TRACE(OUSTR( __FILE__
": identified option \'")
140 + OUString::createFromAscii(option_info
->m_name
) + OUSTR("\'\n"));
145 //==============================================================================
147 bool isBootstrapVariable(sal_uInt32
* pIndex
)
149 OSL_ASSERT(osl_getCommandArgCount() >= *pIndex
);
152 osl_getCommandArg(*pIndex
, &arg
.pData
);
153 if (arg
.matchAsciiL("-env:", 5))
161 //==============================================================================
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"));
181 //##############################################################################
184 struct ExecutableDir
: public rtl::StaticWithInit
<
185 const OUString
, ExecutableDir
> {
186 const OUString
operator () () {
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 () () {
199 tools::getProcessWorkingDir(&workingDir
);
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
223 oslFileError rc
= osl_getFileURLFromSystemPath( sys_path
.pData
, &file_url
.pData
);
224 if ( rc
!= osl_File_E_None
) {
226 if ( osl_getSystemPathFromFileURL( sys_path
.pData
, &tempPath
.pData
) == osl_File_E_None
)
232 throw RuntimeException(
233 OUSTR("cannot get file url from system path: ") +
234 sys_path
, Reference
< XInterface
>() );
239 if (osl_getAbsoluteFileURL(
240 base_url
.pData
, file_url
.pData
, &abs
.pData
) != osl_File_E_None
)
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
>() );
256 return abs
[ abs
.getLength() -1 ] == '/'
257 ? abs
.copy( 0, abs
.getLength() -1 ) : abs
;
260 //##############################################################################
264 //------------------------------------------------------------------------------
265 inline void printf_space( sal_Int32 space
)
268 dp_misc::writeConsole(" ");
271 //------------------------------------------------------------------------------
273 OUString
const & name
, OUString
const & value
, sal_Int32 level
)
275 printf_space( level
);
276 dp_misc::writeConsole(name
+ OUSTR(": ") + value
+ OUSTR("\n"));
279 //------------------------------------------------------------------------------
281 Reference
<deployment::XPackage
> const & xPackage
,
282 Reference
<XCommandEnvironment
> const & xCmdEnv
, sal_Int32 level
)
284 beans::Optional
< OUString
> id(
286 ? beans::Optional
< OUString
>(
287 true, dp_misc::getIdentifier( xPackage
) )
288 : xPackage
->getIdentifier() );
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
) );
299 if (option
.IsPresent
) {
300 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
302 value
= OUSTR("unknown");
304 value
= reg
.Value
? OUSTR("yes") : OUSTR("no");
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");
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();
339 printf_space( level
);
340 dp_misc::writeConsole("<none>\n");
343 for ( sal_Int32 pos
= 0; pos
< len
; ++pos
)
344 printf_package( p
[ pos
], xCmdEnv
, level
);
348 //##############################################################################
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:
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 );
379 //------------------------------------------------------------------------------
380 Reference
<XComponentContext
> connectToOffice(
381 Reference
<XComponentContext
> const & xLocalComponentContext
,
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") );
398 dp_misc::writeConsole(
399 OUSTR("Raising process: ") +
401 OUSTR("\nArguments: -nologo -nodefault ") +
406 ::dp_misc::raiseProcess( appURL
, args
);
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
),
421 dp_misc::writeConsole("Ok.\n");
428 /** returns the path to the lock file used by unopkg.
429 @return the path. An empty string signifies an error.
431 OUString
getLockFilePath()
434 OUString
sBootstrap(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}"));
435 rtl::Bootstrap::expandMacros(sBootstrap
);
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
))
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:
457 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CFG_CacheUrl")),
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
) );
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
477 String
sError(ResId(RID_STR_UNOPKG_ERROR
, *DeploymentResMgr::get()));
479 sMsg
= sMsg
+ OUSTR("\n") + getLockFilePath();
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(),
488 throw RuntimeException( OUSTR("Cannot initialize VCL!"),
491 WarningBox
warn(NULL
, WB_OK
| WB_DEF_OK
, sMsg
);
492 warn
.SetText(::utl::ConfigManager::GetDirectConfigProperty(
493 ::utl::ConfigManager::PRODUCTNAME
).get
<OUString
>());
500 throw LockFileException(
501 OUSTR("\n") + sError
+ sMsg
+ OUSTR("\n"));
505 return xComponentContext
;