1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
|
#include "configinit.hxx"
#include "ssoinit.hxx"
#include "desktop.hrc"
#include "app.hxx"
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif
#ifndef _CPPUHELPER_COMPONENT_CONTEXT_HXX_
#include <cppuhelper/component_context.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _UTL_BOOTSTRAP_HXX
#include <unotools/bootstrap.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#include <stdio.h>
#ifndef _COM_SUN_STAR_LANG_SERVICENOTREGISTEREDEXCEPTION_HPP_
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp>
#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
#include <drafts/com/sun/star/configuration/backend/BackendSetupException.hpp>
#include <drafts/com/sun/star/configuration/backend/AuthenticationFailedException.hpp>
#include <drafts/com/sun/star/configuration/backend/InvalidAuthenticationMechanismException.hpp>
#include <drafts/com/sun/star/configuration/backend/CannotConnectException.hpp>
#include <drafts/com/sun/star/configuration/backend/BackendAccessException.hpp>
#include <drafts/com/sun/star/configuration/backend/InsufficientAccessRightsException.hpp>
// ----------------------------------------------------------------------------
namespace uno = ::com::sun::star::uno;
namespace lang = ::com::sun::star::lang;
namespace configuration = ::com::sun::star::configuration;
namespace backend = drafts::com::sun::star::configuration::backend;
using rtl::OUString;
using uno::UNO_QUERY;
using desktop::Desktop;
// ----------------------------------------------------------------------------
static char const CONFIGURATION_PROVIDER[] = "com.sun.star.configuration.ConfigurationProvider";
static char const LOCAL_BACKEND[] = "com.sun.star.configuration.backend.LocalSingleBackend";
static char const SIMPLE_BACKEND_WRAPPER[] = "com.sun.star.configuration.backend.OnlineBackend";
static char const OFFLINE_BACKEND_WRAPPER[] = "com.sun.star.configuration.backend.OfflineBackend";
#define CFG_PREFIX "com.sun.star.configuration.bootstrap."
static char const OFFLINE_ENTRY[] = CFG_PREFIX "Offline";
static char const SERVICE_ENTRY[] = CFG_PREFIX "BackendService";
static char const WRAPPER_ENTRY[] = CFG_PREFIX "BackendWrapper";
// ----------------------------------------------------------------------------
#define arraysize( arr ) ( sizeof (arr)/sizeof *(arr) )
typedef uno::Reference< lang::XMultiServiceFactory > ConfigurationProvider;
#define OUSTRING( constascii ) OUString( RTL_CONSTASCII_USTRINGPARAM( constascii ) )
#define OU2O( ustr, enc ) rtl::OUStringToOString( (ustr), RTL_TEXTENCODING_ ## enc )
#define k_PROVIDER OUSTRING( CONFIGURATION_PROVIDER )
#define k_LOCALBE OUSTRING( LOCAL_BACKEND )
#define k_SIMPLEWRAPPER OUSTRING( SIMPLE_BACKEND_WRAPPER )
#define k_OFFLINEWRAPPER OUSTRING( OFFLINE_BACKEND_WRAPPER )
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Get a message string securely. There is a fallback string if the resource
// is not available. Adapted from Desktop::GetMsgString()
OUString getMsgString( USHORT nId, char const * aFallBackMsg )
{
ResMgr* pResMgr = Desktop::GetDesktopResManager();
if ( !pResMgr || !nId )
return OUString::createFromAscii(aFallBackMsg);
else
return OUString( ResId( nId, pResMgr ));
}
// ----------------------------------------------------------------------------
/// @attention Must be called (directly or indirectly) from within a catch block
static
bool showFallbackMsg( OUString const & sFallbackMsg,
const rtl::OUString& aMessage)
{
rtl::OUStringBuffer sMsg(aMessage);
sMsg.appendAscii("\n").append( sFallbackMsg );
if ( Application::IsRemoteServer() )
{
rtl::OString aTmpStr = rtl::OUStringToOString( sMsg.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US );
fprintf( stderr, aTmpStr.getStr() );
return true;
}
else
{
WarningBox aMsgBox( NULL, WB_OK_CANCEL | WB_DEF_OK, sMsg.makeStringAndClear() );
return (aMsgBox.Execute() == RET_OK);
}
}
// ----------------------------------------------------------------------------
/// @attention Must be called (directly or indirectly) from within a catch block
static
void showOfflineFallbackMsg( ConfigurationProvider & rxOfflineProvider,
const rtl::OUString& aMessage)
{
OSL_PRECOND( rxOfflineProvider.is(), "Reporting fallback to provider that could not be created" );
rtl::OUStringBuffer aFallbackMsg( getMsgString(STR_CONFIG_WARN_LOCAL_FALLBACK,
"StarOffice will continue the startup using your locally stored personal settings.") );
aFallbackMsg.appendAscii("\n").append( getMsgString(STR_CONFIG_WARN_OFFLINE,
"The changes you have made to your personal settings will be stored locally and "
"synchronized the next time you start StarOffice.") );
if (! showFallbackMsg( aFallbackMsg.makeStringAndClear(), aMessage ) )
rxOfflineProvider.clear();
}
// ----------------------------------------------------------------------------
/// @attention Must be called (directly or indirectly) from within a catch block
static
void showLocalFallbackMsg( ConfigurationProvider & rxLocalProvider,
const rtl::OUString& aMessage)
{
OSL_PRECOND( rxLocalProvider.is(), "Reporting fallback to provider that could not be created" );
rtl::OUString aFallbackMsg( getMsgString(STR_CONFIG_WARN_LOCAL_FALLBACK,
"StarOffice will continue the startup using your locally stored personal settings.") );
if (! showFallbackMsg( aFallbackMsg, aMessage ) )
rxLocalProvider.clear();
}
// ----------------------------------------------------------------------------
/** Called after authentication failures to allow re-login
*/
static
sal_Bool relogin()
{
rtl::OUStringBuffer sMsg( getMsgString( STR_CONFIG_ERR_LOGIN_FAILED,
"Your login to the central configuration was not successful. "
"Either the user name or password is invalid. ") );
sMsg.appendAscii("\n").append( getMsgString( STR_SSO_RELOGIN, "Please log in again.") );
ErrorBox aMsgBox( NULL, WB_RETRY_CANCEL | WB_DEF_RETRY, sMsg.makeStringAndClear() );
if (aMsgBox.Execute() == RET_RETRY)
{
return InitSSO( true );
}
else
return false;
}
// ----------------------------------------------------------------------------
/** Creates the normal configuration provider.
<p> If creation fails because of invalid authentication,
offers the opportunity to re-login where applicable.
</p>
*/
static
ConfigurationProvider createDefaultConfigurationProvider( )
{
uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
OSL_ENSURE( xServiceManager.is(),"No ServiceManager set for CreateApplicationConfigurationProvider");
ConfigurationProvider xProvider;
if (xServiceManager.is())
{
retry:
try
{
xProvider.set( xServiceManager->createInstance(k_PROVIDER), UNO_QUERY);
}
catch (backend::AuthenticationFailedException & e)
{
OSL_TRACE( "Configuration: Authentication failed: %s\n",
OU2O(e.Message,ASCII_US).getStr() );
if (!NeedsLogin())
throw;
if (!relogin())
{
// canceled
OSL_ASSERT( !xProvider.is() );
return xProvider;
}
goto retry;
}
}
if (!xProvider.is())
{
OUString const sMsg = OUSTRING("Service \"") + k_PROVIDER +
OUSTRING("\" is not available at the service manager.");
throw lang::ServiceNotRegisteredException(sMsg, xServiceManager);
}
return xProvider;
}
// ----------------------------------------------------------------------------
static
uno::Reference< uno::XComponentContext >
wrapContext( cppu::ContextEntry_Init * pEntries, sal_Int32 nEntries )
{
uno::Reference< uno::XComponentContext > xBaseContext;
try
{
uno::Reference< ::com::sun::star::beans::XPropertySet >
xPS( ::comphelper::getProcessServiceFactory(), UNO_QUERY );
OSL_ENSURE( xPS.is(), "Cannot get default component context for the process service-manager: no property-set");
if (xPS.is())
{
OSL_VERIFY( xPS->getPropertyValue( OUSTRING( "DefaultContext" ) ) >>= xBaseContext );
}
}
catch (uno::Exception & )
{
OSL_ENSURE( false, "Cannot get default component context for the process service-manager");
}
return cppu::createComponentContext(pEntries, nEntries, xBaseContext);
}
// ----------------------------------------------------------------------------
static
sal_Bool tryCreateConfigurationWithContext( ConfigurationProvider & rxProvider, uno::Reference< uno::XComponentContext > const & xContext )
{
OSL_PRECOND( xContext.is(), "NULL context" );
OSL_PRECOND( !rxProvider.is(), "Provider already set" );
try
{
uno::Reference< lang::XMultiComponentFactory > xFactory = xContext->getServiceManager();
OSL_ENSURE( xFactory.is(), "Context has no service factory !" );
if (xFactory.is())
rxProvider.set( xFactory->createInstanceWithContext( k_PROVIDER, xContext ), UNO_QUERY );
}
catch (uno::Exception & )
{
}
return rxProvider.is();
}
// ----------------------------------------------------------------------------
static
inline
cppu::ContextEntry_Init defineContextEntry( OUString const & name, uno::Any const & value)
{
cppu::ContextEntry_Init entry;
entry.bLateInitService = false;
entry.name = name;
entry.value = value;
return entry;
}
// ----------------------------------------------------------------------------
static
sal_Bool tryCreateOfflineConfiguration( ConfigurationProvider & rxProvider )
{
cppu::ContextEntry_Init aEntries[] =
{
// { false, OUSTRING( WRAPPER_ENTRY ), uno::makeAny<OUString>( k_OFFLINEWRAPPER ) },
defineContextEntry( OUSTRING( OFFLINE_ENTRY ), uno::makeAny<sal_Bool>(sal_True) )
};
return tryCreateConfigurationWithContext( rxProvider, wrapContext(aEntries, arraysize( aEntries )) );
}
// ----------------------------------------------------------------------------
static
sal_Bool tryCreateLocalConfiguration( ConfigurationProvider & rxProvider )
{
cppu::ContextEntry_Init aEntries[] =
{
defineContextEntry( OUSTRING( SERVICE_ENTRY ), uno::makeAny<OUString>( k_LOCALBE ) ),
defineContextEntry( OUSTRING( WRAPPER_ENTRY ), uno::makeAny<OUString>( k_SIMPLEWRAPPER ) ),
defineContextEntry( OUSTRING( OFFLINE_ENTRY ), uno::Any() )
};
return tryCreateConfigurationWithContext( rxProvider, wrapContext(aEntries, arraysize( aEntries )) );
}
// ----------------------------------------------------------------------------
/// @attention this method must be called from a catch statement!
static void handleGeneralException(ConfigurationProvider& xProvider,
uno::Exception& aException,
const rtl::OUString& aMessage)
{
aException.Message = aMessage ;
if (tryCreateLocalConfiguration(xProvider))
{
showLocalFallbackMsg(xProvider, aMessage) ;
}
else { throw ; }
}
// ----------------------------------------------------------------------------
/// @attention this method must be called from a catch statement!
static void handleAccessException(ConfigurationProvider& xProvider,
uno::Exception& aException,
const rtl::OUString& aMessage)
{
aException.Message = aMessage ;
if (tryCreateOfflineConfiguration(xProvider))
{
showOfflineFallbackMsg(xProvider, aMessage) ;
}
else if (tryCreateLocalConfiguration(xProvider))
{
showLocalFallbackMsg(xProvider, aMessage) ;
}
else { throw ; }
}
// ----------------------------------------------------------------------------
/// @attention this method must be called from a catch statement!
static void handleConnectException(ConfigurationProvider& xProvider,
uno::Exception& aException,
const rtl::OUString& aMessage)
{
handleAccessException(xProvider, aException, aMessage) ;
}
// ----------------------------------------------------------------------------
/**
[cm122549]
Ok, I know it looks ugly to have the whole list of exceptions being
caught here in one go, when we have only three different kinds of
behaviour for them. The problem is that there is apparently a bug in
Windows which, if we try to do another throw later to refine our
understanding of the exception, will actually delete the exception
object twice. Which is not nice, especially when considering what
store in those exceptions. Hence the catchfest here once and for
all to be able to generate all the different messages.
*/
uno::Reference< lang::XMultiServiceFactory > CreateApplicationConfigurationProvider( )
{
uno::Reference< lang::XMultiServiceFactory > xProvider;
try
{
xProvider = createDefaultConfigurationProvider( );
}
catch (configuration::InvalidBootstrapFileException & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_SETTINGS_INCOMPLETE,
"The startup settings for accessing the central configuration are incomplete. "));
}
catch (backend::InvalidAuthenticationMechanismException & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_MECHANISM_INVALID,
"The specified authentication method to access the central configuration is not supported. "));
}
catch (backend::AuthenticationFailedException & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_LOGIN_FAILED,
"Your login to the central configuration was not successful. "
"Either the user name or password is invalid. "));
}
catch (backend::CannotConnectException & exception)
{
handleConnectException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT,
"A connection to the central configuration could not be established. "));
}
catch (backend::InsufficientAccessRightsException & exception)
{
handleAccessException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_RIGHTS_MISSING,
"You cannot access the central configuration because of missing access rights. "));
}
catch (backend::BackendAccessException & exception)
{
handleAccessException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_ACCESS_GENERAL,
"A general access error occurred while accessing your central configuration."));
}
catch (backend::BackendSetupException & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT,
"A connection to the central configuration could not be established. "));
}
catch (configuration::CannotLoadConfigurationException & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT,
"A connection to the central configuration could not be established. "));
}
catch (uno::Exception & exception)
{
handleGeneralException(xProvider, exception,
getMsgString( STR_CONFIG_ERR_ACCESS_GENERAL,
"A general error occurred while accessing your central configuration."));
}
return xProvider ;
}
|