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 :
21 : #include <algorithm>
22 :
23 : #include <config_vclplug.h>
24 :
25 : #include "app.hxx"
26 : #include "cmdlineargs.hxx"
27 : #include "desktopresid.hxx"
28 : #include "desktop.hrc"
29 : #include <com/sun/star/registry/XSimpleRegistry.hpp>
30 : #include <com/sun/star/lang/XComponent.hpp>
31 : #include <com/sun/star/lang/XInitialization.hpp>
32 : #include <com/sun/star/uno/Exception.hpp>
33 : #include <com/sun/star/uno/XCurrentContext.hpp>
34 : #include <com/sun/star/packages/zip/ZipIOException.hpp>
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
37 : #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
38 : #include <uno/current_context.hxx>
39 : #include <cppuhelper/bootstrap.hxx>
40 : #include <officecfg/Setup.hxx>
41 : #include <osl/file.hxx>
42 : #include <osl/module.h>
43 : #include <rtl/uri.hxx>
44 : #include <rtl/ustrbuf.hxx>
45 : #include <rtl/bootstrap.hxx>
46 :
47 : #include <tools/rcid.h>
48 :
49 : #include <rtl/instance.hxx>
50 : #include <comphelper/processfactory.hxx>
51 : #include <unotools/localfilehelper.hxx>
52 : #include <unotools/ucbhelper.hxx>
53 : #include <unotools/tempfile.hxx>
54 : #include <vcl/svapp.hxx>
55 : #include <unotools/pathoptions.hxx>
56 :
57 : using namespace desktop;
58 : using namespace ::com::sun::star::uno;
59 : using namespace ::com::sun::star::lang;
60 : using namespace ::com::sun::star::beans;
61 : using namespace ::com::sun::star::registry;
62 : using namespace ::com::sun::star::ucb;
63 :
64 : namespace desktop
65 : {
66 :
67 :
68 :
69 0 : static void configureUcb()
70 : {
71 : SAL_INFO( "desktop.app", "desktop (sb93797) ::configureUcb" );
72 :
73 : // For backwards compatibility, in case some code still uses plain
74 : // createInstance w/o args directly to obtain an instance:
75 0 : UniversalContentBroker::create(comphelper::getProcessComponentContext());
76 :
77 : #if ENABLE_GNOME_VFS
78 : try {
79 : // Instantiate GNOME-VFS UCP in the thread that initialized GNOME in order
80 : // to avoid a deadlock that may occur in case the UCP gets initialized from
81 : // a different thread (which may happen when calling remotely via UNO); this
82 : // is not a fix, just a workaround:
83 : Reference< XCurrentContext > xCurrentContext(getCurrentContext());
84 : Any aValue(xCurrentContext->getValueByName("system.desktop-environment"));
85 : OUString aDesktopEnvironment;
86 : if ((aValue >>= aDesktopEnvironment) && aDesktopEnvironment == "GNOME")
87 : {
88 : Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
89 : UniversalContentBroker::create(xContext)
90 : ->registerContentProvider(
91 : Reference<XContentProvider>(
92 : xContext->getServiceManager()->createInstanceWithContext(
93 : "com.sun.star.ucb.GnomeVFSContentProvider", xContext),
94 : UNO_QUERY_THROW),
95 : ".*", false);
96 : }
97 : }
98 : catch ( const Exception & )
99 : {
100 : SAL_WARN( "desktop.app", "missing gnome-vfs component to initialize thread workaround" );
101 : }
102 : #endif // ENABLE_GNOME_VFS
103 0 : }
104 :
105 1 : void Desktop::InitApplicationServiceManager()
106 : {
107 : SAL_INFO( "desktop.app", "desktop (cd100003) ::createApplicationServiceManager" );
108 1 : Reference<XMultiServiceFactory> sm;
109 : #ifdef ANDROID
110 : OUString aUnoRc( "file:///assets/program/unorc" );
111 : sm.set(
112 : cppu::defaultBootstrap_InitialComponentContext( aUnoRc )->getServiceManager(),
113 : UNO_QUERY_THROW);
114 : #else
115 : sm.set(
116 2 : cppu::defaultBootstrap_InitialComponentContext()->getServiceManager(),
117 1 : UNO_QUERY_THROW);
118 : #endif
119 1 : comphelper::setProcessServiceFactory(sm);
120 1 : }
121 :
122 0 : void Desktop::RegisterServices(Reference< XComponentContext > const & context)
123 : {
124 0 : if( !m_bServicesRegistered )
125 : {
126 : SAL_INFO( "desktop.app", "desktop (cd100003) ::registerServices" );
127 :
128 : // interpret command line arguments
129 0 : CommandLineArgs& rCmdLine = GetCommandLineArgs();
130 :
131 : // Headless mode for FAT Office
132 0 : sal_Bool bHeadlessMode = rCmdLine.IsHeadless();
133 0 : if ( bHeadlessMode )
134 0 : Application::EnableHeadlessMode(false);
135 :
136 : // read accept string from configuration
137 : OUString conDcpCfg(
138 0 : officecfg::Setup::Office::ooSetupConnectionURL::get(context));
139 0 : if (!conDcpCfg.isEmpty()) {
140 0 : createAcceptor(conDcpCfg);
141 : }
142 :
143 0 : std::vector< OUString > const & conDcp = rCmdLine.GetAccept();
144 0 : for (std::vector< OUString >::const_iterator i(conDcp.begin());
145 0 : i != conDcp.end(); ++i)
146 : {
147 0 : createAcceptor(*i);
148 : }
149 :
150 0 : configureUcb();
151 :
152 0 : CreateTemporaryDirectory();
153 0 : m_bServicesRegistered = true;
154 : }
155 0 : }
156 :
157 : namespace
158 : {
159 : struct acceptorMap : public rtl::Static< AcceptorMap, acceptorMap > {};
160 : struct CurrentTempURL : public rtl::Static< OUString, CurrentTempURL > {};
161 : }
162 :
163 : static sal_Bool bAccept = sal_False;
164 :
165 0 : void Desktop::createAcceptor(const OUString& aAcceptString)
166 : {
167 : // check whether the requested acceptor already exists
168 0 : AcceptorMap &rMap = acceptorMap::get();
169 0 : AcceptorMap::const_iterator pIter = rMap.find(aAcceptString);
170 0 : if (pIter == rMap.end() )
171 : {
172 0 : Sequence< Any > aSeq( 2 );
173 0 : aSeq[0] <<= aAcceptString;
174 0 : aSeq[1] <<= bAccept;
175 0 : Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
176 : Reference<XInitialization> rAcceptor(
177 0 : xContext->getServiceManager()->createInstanceWithContext("com.sun.star.office.Acceptor", xContext),
178 0 : UNO_QUERY );
179 0 : if ( rAcceptor.is() )
180 : {
181 : try
182 : {
183 0 : rAcceptor->initialize( aSeq );
184 0 : rMap.insert(AcceptorMap::value_type(aAcceptString, rAcceptor));
185 : }
186 0 : catch (const com::sun::star::uno::Exception& e)
187 : {
188 : // no error handling needed...
189 : // acceptor just won't come up
190 : SAL_WARN( "desktop.app", "Acceptor could not be created: " << e.Message);
191 : }
192 : }
193 : else
194 : {
195 : // there is already an acceptor with this description
196 : SAL_WARN( "desktop.app", "Acceptor already exists.");
197 0 : }
198 : }
199 0 : }
200 :
201 0 : class enable
202 : {
203 : private:
204 : Sequence<Any> m_aSeq;
205 : public:
206 0 : enable() : m_aSeq(1) {
207 0 : m_aSeq[0] <<= sal_True;
208 0 : }
209 0 : void operator() (const AcceptorMap::value_type& val) {
210 0 : if (val.second.is()) {
211 0 : val.second->initialize(m_aSeq);
212 : }
213 0 : }
214 : };
215 :
216 0 : void Desktop::enableAcceptors()
217 : {
218 : SAL_INFO( "desktop.app", "desktop (lo119109) Desktop::enableAcceptors");
219 0 : if (!bAccept)
220 : {
221 : // from now on, all new acceptors are enabled
222 0 : bAccept = sal_True;
223 : // enable existing acceptors by calling initialize(true)
224 : // on all existing acceptors
225 0 : AcceptorMap &rMap = acceptorMap::get();
226 0 : std::for_each(rMap.begin(), rMap.end(), enable());
227 : }
228 0 : }
229 :
230 0 : void Desktop::destroyAcceptor(const OUString& aAcceptString)
231 : {
232 : // special case stop all acceptors
233 0 : AcceptorMap &rMap = acceptorMap::get();
234 0 : if (aAcceptString.equalsAscii("all")) {
235 0 : rMap.clear();
236 :
237 : } else {
238 : // try to remove acceptor from map
239 0 : AcceptorMap::const_iterator pIter = rMap.find(aAcceptString);
240 0 : if (pIter != rMap.end() ) {
241 : // remove reference from map
242 : // this is the last reference and the acceptor will be destructed
243 0 : rMap.erase(aAcceptString);
244 : } else {
245 : SAL_WARN( "desktop.app", "Found no acceptor to remove");
246 : }
247 : }
248 0 : }
249 :
250 :
251 0 : void Desktop::DeregisterServices()
252 : {
253 : // stop all acceptors by clearing the map
254 0 : acceptorMap::get().clear();
255 0 : }
256 :
257 0 : void Desktop::CreateTemporaryDirectory()
258 : {
259 : SAL_INFO( "desktop.app", "desktop (cd100003) ::createTemporaryDirectory" );
260 :
261 0 : OUString aTempBaseURL;
262 : try
263 : {
264 0 : SvtPathOptions aOpt;
265 0 : aTempBaseURL = aOpt.GetTempPath();
266 : }
267 0 : catch (RuntimeException& e)
268 : {
269 : // Catch runtime exception here: We have to add language dependent info
270 : // to the exception message. Fallback solution uses hard coded string.
271 0 : OUString aMsg;
272 0 : DesktopResId aResId( STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE );
273 0 : aResId.SetRT( RSC_STRING );
274 0 : if ( aResId.GetResMgr()->IsAvailable( aResId ))
275 0 : aMsg = OUString( aResId );
276 : else
277 0 : aMsg = "The path manager is not available.\n";
278 0 : e.Message = aMsg + e.Message;
279 0 : throw;
280 : }
281 :
282 : // set temp base directory
283 0 : sal_Int32 nLength = aTempBaseURL.getLength();
284 0 : if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) )
285 0 : aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 );
286 :
287 0 : OUString aRet;
288 0 : OUString aTempPath( aTempBaseURL );
289 :
290 : // create new current temporary directory
291 0 : ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTempBaseURL, aRet );
292 0 : ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath );
293 0 : aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath );
294 0 : if ( aTempPath.isEmpty() )
295 : {
296 0 : ::osl::File::getTempDirURL( aTempBaseURL );
297 :
298 0 : nLength = aTempBaseURL.getLength();
299 0 : if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) )
300 0 : aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 );
301 :
302 0 : aTempPath = aTempBaseURL;
303 0 : ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath );
304 0 : aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath );
305 : }
306 :
307 : // set new current temporary directory
308 0 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTempPath, aRet );
309 0 : CurrentTempURL::get() = aRet;
310 0 : }
311 :
312 0 : void Desktop::RemoveTemporaryDirectory()
313 : {
314 : SAL_INFO( "desktop.app", "desktop (cd100003) ::removeTemporaryDirectory" );
315 :
316 : // remove current temporary directory
317 0 : OUString &rCurrentTempURL = CurrentTempURL::get();
318 0 : if ( !rCurrentTempURL.isEmpty() )
319 : {
320 0 : ::utl::UCBContentHelper::Kill( rCurrentTempURL );
321 : }
322 0 : }
323 :
324 : } // namespace desktop
325 :
326 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|