Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cstring>
23 :
24 : #include "rtl/process.h"
25 : #include "rtl/bootstrap.hxx"
26 : #include "rtl/random.h"
27 : #include "rtl/string.hxx"
28 : #include "rtl/ustrbuf.hxx"
29 : #include "rtl/uri.hxx"
30 : #include "osl/diagnose.h"
31 : #include "osl/file.hxx"
32 : #include "osl/security.hxx"
33 : #include "osl/thread.hxx"
34 :
35 : #include "cppuhelper/bootstrap.hxx"
36 : #include "cppuhelper/findsofficepath.h"
37 :
38 : #include "com/sun/star/uno/XComponentContext.hpp"
39 :
40 : #include "com/sun/star/bridge/UnoUrlResolver.hpp"
41 : #include "com/sun/star/bridge/XUnoUrlResolver.hpp"
42 :
43 : #include "macro_expander.hxx"
44 :
45 : #define ARLEN(x) sizeof (x) / sizeof *(x)
46 :
47 :
48 : using namespace ::rtl;
49 : using namespace ::osl;
50 : using namespace ::com::sun::star;
51 : using namespace ::com::sun::star::uno;
52 :
53 : namespace cppu
54 : {
55 :
56 0 : BootstrapException::BootstrapException()
57 : {
58 0 : }
59 :
60 0 : BootstrapException::BootstrapException( const ::rtl::OUString & rMessage )
61 0 : :m_aMessage( rMessage )
62 : {
63 0 : }
64 :
65 0 : BootstrapException::BootstrapException( const BootstrapException & e )
66 : {
67 0 : m_aMessage = e.m_aMessage;
68 0 : }
69 :
70 0 : BootstrapException::~BootstrapException()
71 : {
72 0 : }
73 :
74 0 : BootstrapException & BootstrapException::operator=( const BootstrapException & e )
75 : {
76 0 : m_aMessage = e.m_aMessage;
77 0 : return *this;
78 : }
79 :
80 0 : const ::rtl::OUString & BootstrapException::getMessage() const
81 : {
82 0 : return m_aMessage;
83 : }
84 :
85 0 : Reference< XComponentContext > SAL_CALL bootstrap()
86 : {
87 0 : Reference< XComponentContext > xRemoteContext;
88 :
89 : try
90 : {
91 0 : char const * p1 = cppuhelper_detail_findSofficePath();
92 0 : if (p1 == NULL) {
93 : throw BootstrapException(
94 0 : "no soffice installation found!");
95 : }
96 0 : rtl::OUString p2;
97 0 : if (!rtl_convertStringToUString(
98 0 : &p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(),
99 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
100 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
101 0 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
102 : {
103 : throw BootstrapException(
104 0 : "bad characters in soffice installation path!");
105 : }
106 0 : OUString path;
107 0 : if (osl::FileBase::getFileURLFromSystemPath(p2, path) !=
108 : osl::FileBase::E_None)
109 : {
110 : throw BootstrapException(
111 0 : "cannot convert soffice installation path to URL!");
112 : }
113 0 : if (!path.isEmpty() && path[path.getLength() - 1] != '/') {
114 0 : path += "/";
115 : }
116 :
117 0 : OUString uri;
118 0 : if (!Bootstrap::get("URE_BOOTSTRAP", uri)) {
119 : Bootstrap::set(
120 : "URE_BOOTSTRAP",
121 0 : Bootstrap::encode(path + SAL_CONFIGFILE("fundamental")));
122 : }
123 :
124 : // create default local component context
125 : Reference< XComponentContext > xLocalContext(
126 0 : defaultBootstrap_InitialComponentContext() );
127 0 : if ( !xLocalContext.is() )
128 0 : throw BootstrapException( "no local component context!" );
129 :
130 : // create a random pipe name
131 0 : rtlRandomPool hPool = rtl_random_createPool();
132 0 : if ( hPool == 0 )
133 0 : throw BootstrapException( "cannot create random pool!" );
134 : sal_uInt8 bytes[ 16 ];
135 0 : if ( rtl_random_getBytes( hPool, bytes, ARLEN( bytes ) )
136 : != rtl_Random_E_None )
137 0 : throw BootstrapException( "random pool error!" );
138 0 : rtl_random_destroyPool( hPool );
139 0 : ::rtl::OUStringBuffer buf;
140 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno" ) );
141 0 : for ( sal_uInt32 i = 0; i < ARLEN( bytes ); ++i )
142 0 : buf.append( static_cast< sal_Int32 >( bytes[ i ] ) );
143 0 : OUString sPipeName( buf.makeStringAndClear() );
144 :
145 : // accept string
146 : OSL_ASSERT( buf.isEmpty() );
147 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "--accept=pipe,name=" ) );
148 0 : buf.append( sPipeName );
149 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ";urp;" ) );
150 :
151 : // arguments
152 : OUString args [] = {
153 : OUString("--nologo"),
154 : OUString("--nodefault"),
155 : OUString("--norestore"),
156 : OUString("--nocrashreport"),
157 : OUString("--nolockcheck"),
158 : buf.makeStringAndClear()
159 0 : };
160 : rtl_uString * ar_args [] = {
161 : args[ 0 ].pData,
162 : args[ 1 ].pData,
163 : args[ 2 ].pData,
164 : args[ 3 ].pData,
165 : args[ 4 ].pData,
166 : args[ 5 ].pData
167 0 : };
168 0 : ::osl::Security sec;
169 :
170 : // start office process
171 0 : oslProcess hProcess = 0;
172 : oslProcessError rc = osl_executeProcess(
173 0 : OUString(path + "soffice").pData, ar_args, ARLEN( ar_args ),
174 : osl_Process_DETACHED,
175 : sec.getHandle(),
176 : 0, // => current working dir
177 : 0, 0, // => no env vars
178 0 : &hProcess );
179 0 : switch ( rc )
180 : {
181 : case osl_Process_E_None:
182 0 : osl_freeProcessHandle( hProcess );
183 0 : break;
184 : case osl_Process_E_NotFound:
185 0 : throw BootstrapException( "image not found!" );
186 : case osl_Process_E_TimedOut:
187 0 : throw BootstrapException( "timout occurred!" );
188 : case osl_Process_E_NoPermission:
189 0 : throw BootstrapException( "permission denied!" );
190 : case osl_Process_E_Unknown:
191 0 : throw BootstrapException( "unknown error!" );
192 : case osl_Process_E_InvalidError:
193 : default:
194 0 : throw BootstrapException( "unmapped error!" );
195 : }
196 :
197 : // create a URL resolver
198 : Reference< bridge::XUnoUrlResolver > xUrlResolver(
199 0 : bridge::UnoUrlResolver::create( xLocalContext ) );
200 :
201 : // connection string
202 : OSL_ASSERT( buf.isEmpty() );
203 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "uno:pipe,name=" ) );
204 0 : buf.append( sPipeName );
205 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
206 0 : ";urp;StarOffice.ComponentContext" ) );
207 0 : OUString sConnectString( buf.makeStringAndClear() );
208 :
209 : // wait until office is started
210 : for ( ; ; )
211 : {
212 : try
213 : {
214 : // try to connect to office
215 : xRemoteContext.set(
216 0 : xUrlResolver->resolve( sConnectString ), UNO_QUERY_THROW );
217 0 : break;
218 : }
219 0 : catch ( connection::NoConnectException & )
220 : {
221 : // wait 500 ms, then try to connect again
222 0 : TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ };
223 0 : ::osl::Thread::wait( tv );
224 : }
225 0 : }
226 : }
227 0 : catch ( Exception & e )
228 : {
229 : throw BootstrapException(
230 0 : "unexpected UNO exception caught: " + e.Message );
231 : }
232 :
233 0 : return xRemoteContext;
234 : }
235 :
236 10129 : OUString bootstrap_expandUri(OUString const & uri) {
237 : static char const PREFIX[] = "vnd.sun.star.expand:";
238 10129 : return uri.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(PREFIX))
239 : ? cppuhelper::detail::expandMacros(
240 : rtl::Uri::decode(
241 10129 : uri.copy(RTL_CONSTASCII_LENGTH(PREFIX)),
242 : rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8))
243 20258 : : uri;
244 : }
245 :
246 : } // namespace cppu
247 :
248 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|