1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_unotools.hxx"
26 #ifndef GCC
27 #endif
28 
29 //_________________________________________________________________________________________________________________
30 //	includes
31 //_________________________________________________________________________________________________________________
32 
33 #include <unotools/startoptions.hxx>
34 #include <unotools/configmgr.hxx>
35 #include <unotools/configitem.hxx>
36 #include <tools/debug.hxx>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <com/sun/star/uno/Sequence.hxx>
39 
40 #include <rtl/logfile.hxx>
41 #include "itemholder1.hxx"
42 //_________________________________________________________________________________________________________________
43 //	namespaces
44 //_________________________________________________________________________________________________________________
45 
46 using namespace ::utl					;
47 using namespace ::rtl					;
48 using namespace ::osl					;
49 using namespace ::com::sun::star::uno	;
50 
51 //_________________________________________________________________________________________________________________
52 //	const
53 //_________________________________________________________________________________________________________________
54 
55 #define	DEFAULT_SHOWINTRO				sal_True
56 #define	DEFAULT_CONNECTIONURL			OUString()
57 
58 #define	ROOTNODE_START			   		OUString(RTL_CONSTASCII_USTRINGPARAM("Setup/Office"	))
59 #define	PROPERTYNAME_SHOWINTRO			OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupShowIntro"	))
60 #define	PROPERTYNAME_CONNECTIONURL		OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupConnectionURL"	))
61 
62 #define	PROPERTYHANDLE_SHOWINTRO		0
63 #define	PROPERTYHANDLE_CONNECTIONURL	1
64 
65 #define	PROPERTYCOUNT					2
66 
67 //_________________________________________________________________________________________________________________
68 //	private declarations!
69 //_________________________________________________________________________________________________________________
70 
71 class SvtStartOptions_Impl : public ConfigItem
72 {
73 	//-------------------------------------------------------------------------------------------------------------
74 	//	public methods
75 	//-------------------------------------------------------------------------------------------------------------
76 
77 	public:
78 
79 		//---------------------------------------------------------------------------------------------------------
80 		//	constructor / destructor
81 		//---------------------------------------------------------------------------------------------------------
82 
83 		 SvtStartOptions_Impl();
84 		~SvtStartOptions_Impl();
85 
86 		//---------------------------------------------------------------------------------------------------------
87 		//	overloaded methods of baseclass
88 		//---------------------------------------------------------------------------------------------------------
89 
90 		/*-****************************************************************************************************//**
91 			@short		called for notify of configmanager
92 			@descr		These method is called from the ConfigManager before application ends or from the
93 			 			PropertyChangeListener if the sub tree broadcasts changes. You must update your
94 						internal values.
95 
96 			@ATTENTION	We don't implement these method - because we support readonly values at runtime only!
97 
98 			@seealso	baseclass ConfigItem
99 
100 			@param		"seqPropertyNames" is the list of properties which should be updated.
101 			@return		-
102 
103 			@onerror	-
104 		*//*-*****************************************************************************************************/
105 
106     	virtual void Notify( const Sequence< OUString >& seqPropertyNames );
107 
108 		/*-****************************************************************************************************//**
109 			@short		write changes to configuration
110 			@descr		These method writes the changed values into the sub tree
111 						and should always called in our destructor to guarantee consistency of config data.
112 
113 			@ATTENTION	We don't implement these method - because we support readonly values at runtime only!
114 
115 			@seealso	baseclass ConfigItem
116 
117 			@param		-
118 			@return		-
119 
120 			@onerror	-
121 		*//*-*****************************************************************************************************/
122 
123     	virtual void Commit();
124 
125 		//---------------------------------------------------------------------------------------------------------
126 		//	public interface
127 		//---------------------------------------------------------------------------------------------------------
128 
129 		/*-****************************************************************************************************//**
130 			@short		access method to get internal values
131 			@descr		These method give us a chance to regulate acces to ouer internal values.
132 						It's not used in the moment - but it's possible for the feature!
133 
134 			@seealso	-
135 
136 			@param		-
137 			@return		-
138 
139 			@onerror	-
140 		*//*-*****************************************************************************************************/
141 
142 		sal_Bool	IsIntroEnabled	(						) const	;
143 		void		EnableIntro		( sal_Bool bState		)		;
144 		OUString	GetConnectionURL(						) const	;
145 		void		SetConnectionURL( const OUString& sURL	)		;
146 
147 	//-------------------------------------------------------------------------------------------------------------
148 	//	private methods
149 	//-------------------------------------------------------------------------------------------------------------
150 
151 	private:
152 
153 		/*-****************************************************************************************************//**
154 			@short		return list of fix key names of ouer configuration management which represent oue module tree
155 			@descr		These methods return a static const list of key names. We need it to get needed values from our
156 						configuration management. We return well known key names only - because the "UserData" node
157 						is handled in a special way!
158 
159 			@seealso	-
160 
161 			@param		-
162 			@return		A list of needed configuration keys is returned.
163 
164 			@onerror	-
165 		*//*-*****************************************************************************************************/
166 
167 		static Sequence< OUString > impl_GetPropertyNames();
168 
169 	//-------------------------------------------------------------------------------------------------------------
170 	//	private member
171 	//-------------------------------------------------------------------------------------------------------------
172 
173 	private:
174 
175 		sal_Bool	m_bShowIntro		;	/// cache "ShowIntro" of Start section
176 		OUString	m_sConnectionURL	;	/// cache "Connection" of Start section
177 };
178 
179 //_________________________________________________________________________________________________________________
180 //	definitions
181 //_________________________________________________________________________________________________________________
182 
183 //*****************************************************************************************************************
184 //	constructor
185 //*****************************************************************************************************************
186 SvtStartOptions_Impl::SvtStartOptions_Impl()
187 	// Init baseclasses first
188     :	ConfigItem			( ROOTNODE_START	)
189 	// Init member then.
190 	,	m_bShowIntro		( DEFAULT_SHOWINTRO	)
191 {
192 	// Use our static list of configuration keys to get his values.
193 	Sequence< OUString >	seqNames	= impl_GetPropertyNames();
194 	Sequence< Any >			seqValues	= GetProperties( seqNames )	;
195 
196 	// Safe impossible cases.
197 	// We need values from ALL configuration keys.
198 	// Follow assignment use order of values in relation to our list of key names!
199 	DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtStartOptions_Impl::SvtStartOptions_Impl()\nI miss some values of configuration keys!\n" );
200 
201 	// Copy values from list in right order to ouer internal member.
202 	sal_Int32 nPropertyCount	=	seqValues.getLength()	;
203 	sal_Int32 nProperty			=	0						;
204 	for( nProperty=0; nProperty<nPropertyCount; ++nProperty )
205 	{
206 		// Safe impossible cases.
207 		// Check any for valid value.
208 		DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtStartOptions_Impl::SvtStartOptions_Impl()\nInvalid property value for property detected!\n" );
209         switch( nProperty )
210         {
211             case PROPERTYHANDLE_SHOWINTRO		:	{
212 										 	   			DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtStartOptions_Impl::SvtStartOptions_Impl()\nWho has changed the value type of \"Office.Common\\Start\\ShowIntro\"?" );
213 														seqValues[nProperty] >>= m_bShowIntro;
214 													}
215 													break;
216 
217             case PROPERTYHANDLE_CONNECTIONURL	:	{
218 										 				DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_STRING), "SvtStartOptions_Impl::SvtStartOptions_Impl()\nWho has changed the value type of \"Office.Common\\Start\\Connection\"?" );
219 														seqValues[nProperty] >>= m_sConnectionURL;
220 													}
221 													break;
222         }
223 	}
224 
225 	// Don't enable notification mechanism of ouer baseclass!
226 	// We support readonly variables in the moment.
227 }
228 
229 //*****************************************************************************************************************
230 //	destructor
231 //*****************************************************************************************************************
232 SvtStartOptions_Impl::~SvtStartOptions_Impl()
233 {
234 	// We must save our current values .. if user forget it!
235 	if( IsModified() == sal_True )
236 	{
237 		Commit();
238 	}
239 }
240 
241 //*****************************************************************************************************************
242 //	public method
243 //*****************************************************************************************************************
244 void SvtStartOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
245 {
246 	// Use given list of updated properties to get his values from configuration directly!
247 	Sequence< Any > seqValues = GetProperties( seqPropertyNames );
248 	// Safe impossible cases.
249 	// We need values from ALL notified configuration keys.
250 	DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtStartOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
251 	// Step over list of property names and get right value from coreesponding value list to set it on internal members!
252 	sal_Int32 nCount = seqPropertyNames.getLength();
253 	for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
254 	{
255 		if( seqPropertyNames[nProperty] == PROPERTYNAME_SHOWINTRO )
256 		{
257 			DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_BOOLEAN), "SvtStartOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\Start\\ShowIntro\"?" );
258 			seqValues[nProperty] >>= m_bShowIntro;
259 		}
260 		else
261 		if( seqPropertyNames[nProperty] == PROPERTYNAME_CONNECTIONURL )
262 		{
263 			DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_STRING), "SvtStartOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\Start\\Connection\"?" );
264 			seqValues[nProperty] >>= m_sConnectionURL;
265 		}
266         #if OSL_DEBUG_LEVEL > 1
267 		else DBG_ASSERT( sal_False, "SvtStartOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
268 		#endif
269 	}
270 }
271 
272 //*****************************************************************************************************************
273 //	public method
274 //*****************************************************************************************************************
275 void SvtStartOptions_Impl::Commit()
276 {
277 	// Get names of supported properties, create a list for values and copy current values to it.
278 	Sequence< OUString >	seqNames	= impl_GetPropertyNames();
279 	sal_Int32				nCount		= seqNames.getLength();
280 	Sequence< Any >			seqValues	( nCount );
281 	for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
282 	{
283         switch( nProperty )
284         {
285             case PROPERTYHANDLE_SHOWINTRO		:	{
286                 						 				seqValues[nProperty] <<= m_bShowIntro;
287 										 			}
288                 						 			break;
289             case PROPERTYHANDLE_CONNECTIONURL	:	{
290 	                						 			seqValues[nProperty] <<= m_sConnectionURL;
291 											 		}
292         	        						 		break;
293         }
294 	}
295 	// Set properties in configuration.
296 	PutProperties( seqNames, seqValues );
297 }
298 
299 //*****************************************************************************************************************
300 //	public method
301 //*****************************************************************************************************************
302 sal_Bool SvtStartOptions_Impl::IsIntroEnabled() const
303 {
304 	return m_bShowIntro;
305 }
306 
307 //*****************************************************************************************************************
308 //	public method
309 //*****************************************************************************************************************
310 void SvtStartOptions_Impl::EnableIntro( sal_Bool bState )
311 {
312 	m_bShowIntro = bState;
313 	SetModified();
314 }
315 
316 //*****************************************************************************************************************
317 //	public method
318 //*****************************************************************************************************************
319 OUString SvtStartOptions_Impl::GetConnectionURL() const
320 {
321 	return m_sConnectionURL;
322 }
323 
324 //*****************************************************************************************************************
325 //	public method
326 //*****************************************************************************************************************
327 void SvtStartOptions_Impl::SetConnectionURL( const OUString& sURL )
328 {
329 	m_sConnectionURL = sURL;
330 	SetModified();
331 }
332 
333 //*****************************************************************************************************************
334 //	private method
335 //*****************************************************************************************************************
336 Sequence< OUString > SvtStartOptions_Impl::impl_GetPropertyNames()
337 {
338 	// Build static list of configuration key names.
339 	static const OUString pProperties[] =
340 	{
341 		PROPERTYNAME_SHOWINTRO		,
342 		PROPERTYNAME_CONNECTIONURL	,
343 	};
344 	// Initialize return sequence with these list ...
345 	static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
346 	// ... and return it.
347 	return seqPropertyNames;
348 }
349 
350 //*****************************************************************************************************************
351 //	initialize static member
352 //	DON'T DO IT IN YOUR HEADER!
353 //	see definition for further informations
354 //*****************************************************************************************************************
355 SvtStartOptions_Impl*	SvtStartOptions::m_pDataContainer	= NULL	;
356 sal_Int32				SvtStartOptions::m_nRefCount		= 0		;
357 
358 //*****************************************************************************************************************
359 //	constructor
360 //*****************************************************************************************************************
361 SvtStartOptions::SvtStartOptions()
362 {
363     // Global access, must be guarded (multithreading!).
364     MutexGuard aGuard( GetOwnStaticMutex() );
365 	// Increase ouer refcount ...
366 	++m_nRefCount;
367 	// ... and initialize ouer data container only if it not already!
368     if( m_pDataContainer == NULL )
369 	{
370         RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtStartOptions_Impl::ctor()");
371         m_pDataContainer = new SvtStartOptions_Impl();
372 
373         ItemHolder1::holdConfigItem(E_STARTOPTIONS);
374 	}
375 }
376 
377 //*****************************************************************************************************************
378 //	destructor
379 //*****************************************************************************************************************
380 SvtStartOptions::~SvtStartOptions()
381 {
382     // Global access, must be guarded (multithreading!)
383     MutexGuard aGuard( GetOwnStaticMutex() );
384 	// Decrease ouer refcount.
385 	--m_nRefCount;
386 	// If last instance was deleted ...
387 	// we must destroy ouer static data container!
388     if( m_nRefCount <= 0 )
389 	{
390 		delete m_pDataContainer;
391 		m_pDataContainer = NULL;
392 	}
393 }
394 
395 //*****************************************************************************************************************
396 //	public method
397 //*****************************************************************************************************************
398 sal_Bool SvtStartOptions::IsIntroEnabled() const
399 {
400     MutexGuard aGuard( GetOwnStaticMutex() );
401 	return m_pDataContainer->IsIntroEnabled();
402 }
403 
404 //*****************************************************************************************************************
405 //	public method
406 //*****************************************************************************************************************
407 void SvtStartOptions::EnableIntro( sal_Bool bState )
408 {
409     MutexGuard aGuard( GetOwnStaticMutex() );
410 	m_pDataContainer->EnableIntro( bState );
411 }
412 
413 //*****************************************************************************************************************
414 //	public method
415 //*****************************************************************************************************************
416 OUString SvtStartOptions::GetConnectionURL() const
417 {
418     MutexGuard aGuard( GetOwnStaticMutex() );
419 	return m_pDataContainer->GetConnectionURL();
420 }
421 
422 //*****************************************************************************************************************
423 //	public method
424 //*****************************************************************************************************************
425 void SvtStartOptions::SetConnectionURL( const OUString& sURL )
426 {
427     MutexGuard aGuard( GetOwnStaticMutex() );
428 	m_pDataContainer->SetConnectionURL( sURL );
429 }
430 
431 //*****************************************************************************************************************
432 //	private method
433 //*****************************************************************************************************************
434 Mutex& SvtStartOptions::GetOwnStaticMutex()
435 {
436 	// Initialize static mutex only for one time!
437     static Mutex* pMutex = NULL;
438 	// If these method first called (Mutex not already exist!) ...
439     if( pMutex == NULL )
440     {
441 		// ... we must create a new one. Protect follow code with the global mutex -
442 		// It must be - we create a static variable!
443         MutexGuard aGuard( Mutex::getGlobalMutex() );
444 		// We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
445         if( pMutex == NULL )
446         {
447 			// Create the new mutex and set it for return on static variable.
448             static Mutex aMutex;
449             pMutex = &aMutex;
450         }
451     }
452 	// Return new created or already existing mutex object.
453     return *pMutex;
454 }
455