Update ooo320-m1
[ooovba.git] / svtools / source / config / regoptions.cxx
blob16492586a70012ce5c051d0ccb9d4c44d210a869
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: regoptions.cxx,v $
10 * $Revision: 1.8 $
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_svtools.hxx"
33 #include "regoptions.hxx"
34 #include <unotools/confignode.hxx>
35 #include <tools/date.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <osl/mutex.hxx>
38 #include <unotools/bootstrap.hxx>
39 #include <rtl/ustring.hxx>
41 //........................................................................
42 namespace svt
44 //........................................................................
46 using namespace ::utl;
47 using namespace ::com::sun::star::uno;
49 //====================================================================
50 //= local helpers
51 //====================================================================
52 //--------------------------------------------------------------------
53 /** converts a string representation of a date into a integer representation
54 <p>No semantic check is made, i.e. if the string describes the 40.12, this is not recognized. In opposite,
55 the string must have a valid structure (DD.MM.YYYY).</p>
56 @return
57 the integer representation of the date which can be used with the Date class,
58 or 0 if the given string was no valid date representation
60 static sal_Int32 lcl_convertString2Date( const ::rtl::OUString& _rStringRep )
62 sal_Int32 nDateIntRep = 0;
63 if ( _rStringRep.getLength() == 2 + 1 + 2 + 1 + 4 ) // DD.MM.YYYY
65 // validate the string
66 sal_Bool bValid = sal_True;
68 const sal_Unicode* pStringRep = _rStringRep.getStr();
69 sal_Int32 nLen = _rStringRep.getLength();
70 for ( sal_Int32 nPos = 0;
71 bValid && ( nPos < nLen );
72 ++nPos, ++pStringRep
75 if ( ( 2 == nPos ) || ( 5 == nPos ) )
76 bValid = '.' == *pStringRep; // the number separators
77 else
78 bValid = ( *pStringRep >= '0' ) && ( *pStringRep <= '9' );
81 // passed the test?
82 if ( bValid )
84 Date aDate;
85 aDate.SetDay ( (USHORT)_rStringRep.copy( 0, 2 ).toInt32( ) );
86 aDate.SetMonth ( (USHORT)_rStringRep.copy( 3, 2 ).toInt32( ) );
87 aDate.SetYear ( (USHORT)_rStringRep.copy( 6, 4 ).toInt32( ) );
88 nDateIntRep = aDate.GetDate();
92 return nDateIntRep;
95 //--------------------------------------------------------------------
96 static const ::rtl::OUString& lcl_fillToken( const sal_Int32 /* [in] */ _nToken, const sal_Int16 /* [in] */ _nDigits, ::rtl::OUString& /* [out] */ _rToken )
98 // convert into string
99 ::rtl::OUString sLeanToken = ::rtl::OUString::valueOf( _nToken );
100 // check length
101 if ( sLeanToken.getLength() < _nDigits )
102 { // fill
103 OSL_ENSURE( _nDigits <= 4, "lcl_fillToken: invalid digit number!" );
104 _rToken = ::rtl::OUString( "0000", _nDigits - sLeanToken.getLength(), RTL_TEXTENCODING_ASCII_US );
105 _rToken += sLeanToken;
107 else
108 _rToken = sLeanToken;
110 return _rToken;
113 //--------------------------------------------------------------------
114 /** converts a integer representation of a date into a string representation
116 static ::rtl::OUString lcl_ConvertDate2String( const Date& _rDate )
118 OSL_ENSURE( _rDate.IsValid(), "lcl_ConvertDate2String: invalid integer representation!" );
120 sal_Unicode cSeparator( '.' );
121 ::rtl::OUString sSeparator( &cSeparator, 1 );
123 ::rtl::OUString sStringRep;
124 ::rtl::OUString sToken;
125 sStringRep += lcl_fillToken( (sal_Int32)_rDate.GetDay(), 2, sToken );
126 sStringRep += sSeparator;
127 sStringRep += lcl_fillToken( (sal_Int32)_rDate.GetMonth(), 2, sToken );
128 sStringRep += sSeparator;
129 sStringRep += lcl_fillToken( (sal_Int32)_rDate.GetYear(), 4, sToken );
131 return sStringRep;
134 //--------------------------------------------------------------------
135 /// checks whether a given trigger date is reached (i.e. is _before_ the current date)
136 static sal_Bool lcl_reachedTriggerDate( const Date& _rTriggerDate )
138 return _rTriggerDate <= Date();
141 //--------------------------------------------------------------------
142 #define DECLARE_STATIC_LAZY_USTRING( name ) \
143 static const ::rtl::OUString& lcl_get##name##Name() \
145 static const ::rtl::OUString sName = ::rtl::OUString::createFromAscii( #name ); \
146 return sName; \
149 DECLARE_STATIC_LAZY_USTRING( ReminderDate );
150 DECLARE_STATIC_LAZY_USTRING( RequestDialog );
151 DECLARE_STATIC_LAZY_USTRING( ShowMenuItem );
152 DECLARE_STATIC_LAZY_USTRING( Patch );
154 //====================================================================
155 //= RegOptionsImpl
156 //====================================================================
157 class RegOptionsImpl
159 private:
160 OConfigurationTreeRoot m_aRegistrationNode; // the configuration node we need to access our persistent data
162 String m_sRegistrationURL; // the URL to use when doing an online registration
163 Date m_aReminderDate; // the reminder date as found in the configuration
164 sal_Int32 m_nDialogCounter; // the dialog counter - see getDialogPermission
165 sal_Bool m_bShowMenuItem; // the flag indicating if the registration menu item is allowed
167 static RegOptionsImpl* s_pSingleInstance; // the one and only instance of this class
168 static sal_Int32 s_nInstanceCount; // reference counter for the instances
169 static sal_Bool s_bThisSessionDone; // the flag indicating if for this session, everything beeing relevant has already been done
171 private:
172 RegOptionsImpl( );
174 static ::osl::Mutex& getStaticMutex(); // get the mutex used to protect the static members of this class
176 void commit( );
177 sal_Int32 getBuildId() const;
179 private:
180 RegOptions::DialogPermission implGetDialogPermission( ) const;
182 public:
183 static RegOptionsImpl* registerClient( );
184 static void revokeClient( );
186 inline sal_Bool hasURL( ) const { return ( 0 != m_sRegistrationURL.Len() ); }
187 inline sal_Bool allowMenu( ) const { return hasURL() && m_bShowMenuItem; }
188 inline String getRegistrationURL( ) const { return m_sRegistrationURL; }
190 RegOptions::DialogPermission getDialogPermission( ) const;
191 void markSessionDone( );
192 void activateReminder( sal_Int32 _nDaysFromNow );
193 void removeReminder();
194 bool hasReminderDateCome() const;
197 //--------------------------------------------------------------------
198 RegOptionsImpl* RegOptionsImpl::s_pSingleInstance = NULL;
199 sal_Bool RegOptionsImpl::s_bThisSessionDone = sal_False;
200 sal_Int32 RegOptionsImpl::s_nInstanceCount = 0;
202 //--------------------------------------------------------------------
203 ::osl::Mutex& RegOptionsImpl::getStaticMutex()
205 static ::osl::Mutex* s_pStaticMutex = NULL;
206 if ( !s_pStaticMutex )
208 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
209 if ( !s_pStaticMutex )
211 static ::osl::Mutex s_aStaticMutex;
212 s_pStaticMutex = &s_aStaticMutex;
215 return *s_pStaticMutex;
218 //--------------------------------------------------------------------
219 void RegOptionsImpl::commit( )
221 m_aRegistrationNode.commit( );
224 //--------------------------------------------------------------------
225 RegOptionsImpl* RegOptionsImpl::registerClient( )
227 ::osl::MutexGuard aGuard( getStaticMutex() );
229 if ( !s_pSingleInstance )
230 s_pSingleInstance = new RegOptionsImpl;
232 ++s_nInstanceCount;
233 return s_pSingleInstance;
236 //--------------------------------------------------------------------
237 void RegOptionsImpl::revokeClient( )
239 ::osl::MutexGuard aGuard( getStaticMutex() );
240 OSL_ENSURE( s_nInstanceCount, "RegOptionsImpl::revokeClient: there are no clients alive!" );
241 OSL_ENSURE( s_pSingleInstance || !s_nInstanceCount, "RegOptionsImpl::revokeClient: invalid instance pointer!" );
243 if ( s_nInstanceCount )
245 if ( s_pSingleInstance )
246 // commit the changes done by this client
247 s_pSingleInstance->commit();
249 if ( 0 == --s_nInstanceCount )
251 delete s_pSingleInstance;
252 s_pSingleInstance = NULL;
257 //--------------------------------------------------------------------
258 RegOptionsImpl::RegOptionsImpl( )
259 :m_nDialogCounter ( 0 )
260 ,m_bShowMenuItem ( sal_False )
262 // create the config node for all our registration information
263 m_aRegistrationNode = OConfigurationTreeRoot::createWithServiceFactory(
264 ::comphelper::getProcessServiceFactory(),
265 ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Common/Help/Registration" )
268 // cache some data
269 //the URL to use for online registration
270 ::rtl::OUString sStringValue;
271 m_aRegistrationNode.getNodeValue( ::rtl::OUString::createFromAscii( "URL" ) ) >>= sStringValue;
272 m_sRegistrationURL = sStringValue;
274 // the state of the dialog
275 m_aRegistrationNode.getNodeValue( lcl_getRequestDialogName() ) >>= m_nDialogCounter;
277 // the flag for showing the menu item
278 sal_Bool bBoolValue = sal_False;
279 m_aRegistrationNode.getNodeValue( lcl_getShowMenuItemName() ) >>= bBoolValue;
280 m_bShowMenuItem = bBoolValue;
282 // the reminder date (if any)
283 sal_Int32 nIntDate = 0;
284 sStringValue = ::rtl::OUString();
285 m_aRegistrationNode.getNodeValue( lcl_getReminderDateName() ) >>= sStringValue;
286 bool bIsPatchDate = ( sStringValue.equals( lcl_getPatchName() ) != sal_False );
287 if ( !bIsPatchDate && sStringValue.getLength() )
288 nIntDate = lcl_convertString2Date( sStringValue );
289 m_aReminderDate.SetDate( nIntDate );
292 //--------------------------------------------------------------------
293 RegOptions::DialogPermission RegOptionsImpl::implGetDialogPermission( ) const
295 RegOptions::DialogPermission eResult = RegOptions::dpDisabled;
296 // no URL or a counter already decreased to zero means the dialog is disabled
297 if ( hasURL() && ( m_nDialogCounter > 0 ) )
299 // during every session, the counter will be decreased
300 // If it reaches zero, the dialog shall be executed
301 if ( 1 == m_nDialogCounter )
303 if ( m_aReminderDate.IsValid( ) )
304 { // valid reminder date
305 // assume remind later
306 eResult = RegOptions::dpRemindLater;
307 // and check if we reached the reminder date
308 if ( lcl_reachedTriggerDate( m_aReminderDate ) )
309 eResult = RegOptions::dpThisSession;
311 else
312 eResult = RegOptions::dpThisSession; // execute in this session
314 else
315 eResult = RegOptions::dpNotThisSession; // first trigger session not reached
317 // a last check ....
318 if ( ( s_bThisSessionDone ) // this session is already marked as "done"
319 && ( RegOptions::dpThisSession == eResult )// but without this, the state would be "now"
321 eResult = RegOptions::dpDisabled; // -> change state to "disabled"
324 return eResult;
327 //--------------------------------------------------------------------
328 RegOptions::DialogPermission RegOptionsImpl::getDialogPermission( ) const
330 OSL_ENSURE( !s_bThisSessionDone, "RegOptionsImpl::getDialogPermission: should never be asked in this session, again!" );
331 // Somebody already marked this session as "everything relevant happened". So why sombody (else?) asks
332 // me again?
334 return implGetDialogPermission( );
337 //--------------------------------------------------------------------
338 void RegOptionsImpl::activateReminder( sal_Int32 _nDaysFromNow )
340 OSL_ENSURE( s_bThisSessionDone || ( implGetDialogPermission( ) != RegOptions::dpDisabled ), "RegOptionsImpl::activateReminder: invalid call!" );
341 OSL_ENSURE( _nDaysFromNow > 0, "RegOptionsImpl::activateReminder: invalid argument!" );
343 // calc the reminder
344 m_aReminderDate = Date() + _nDaysFromNow; // today (default ctor) + days
346 // remember the date
347 m_aRegistrationNode.setNodeValue(
348 lcl_getReminderDateName(),
349 makeAny( lcl_ConvertDate2String( m_aReminderDate ) )
351 // to be on the save side, write the counter
352 m_aRegistrationNode.setNodeValue(
353 lcl_getRequestDialogName(),
354 makeAny( (sal_Int32)1 )
357 // mark this session as done
358 if ( !s_bThisSessionDone )
359 markSessionDone( );
362 //--------------------------------------------------------------------
363 void RegOptionsImpl::removeReminder()
365 ::rtl::OUString aDefault;
366 ::rtl::OUString aReminderValue( lcl_getPatchName() );
367 aReminderValue += ::rtl::OUString::valueOf(getBuildId());
369 m_aRegistrationNode.setNodeValue(
370 lcl_getReminderDateName(),
371 Any( aReminderValue )
375 //--------------------------------------------------------------------
376 sal_Int32 RegOptionsImpl::getBuildId() const
378 sal_Int32 nBuildId( 0 );
379 ::rtl::OUString aDefault;
380 ::rtl::OUString aBuildIdData = utl::Bootstrap::getBuildIdData( aDefault );
381 sal_Int32 nIndex1 = aBuildIdData.indexOf(':');
382 sal_Int32 nIndex2 = aBuildIdData.indexOf(')');
383 if (( nIndex1 > 0 ) && ( nIndex2 > 0 ) && ( nIndex2-1 > nIndex1+1 ))
385 ::rtl::OUString aBuildId = aBuildIdData.copy( nIndex1+1, nIndex2-nIndex1-1 );
386 nBuildId = aBuildId.toInt32();
389 return nBuildId;
392 //--------------------------------------------------------------------
393 bool RegOptionsImpl::hasReminderDateCome() const
395 bool bRet = false;
396 sal_Int32 nDate = 0;
397 ::rtl::OUString sDate;
398 m_aRegistrationNode.getNodeValue( lcl_getReminderDateName() ) >>= sDate;
399 if ( sDate.getLength() )
401 if ( sDate.indexOf( lcl_getPatchName() ) == 0)
403 if (sDate.equals( lcl_getPatchName() ))
404 bRet = true;
405 else if (sDate.getLength() > lcl_getPatchName().getLength() )
407 // Check the build ID to determine if the registration
408 // dialog needs to be shown.
409 sal_Int32 nBuildId = getBuildId();
410 ::rtl::OUString aStoredBuildId( sDate.copy(lcl_getPatchName().getLength()));
412 // remind if the current build ID is not the same as the stored one
413 if ( nBuildId != aStoredBuildId.toInt32() )
414 bRet = true;
417 else
419 nDate = lcl_convertString2Date( sDate );
420 if ( nDate > 0 )
422 Date aReminderDate;
423 aReminderDate.SetDate( nDate );
424 bRet = aReminderDate <= Date();
428 else
429 bRet = true;
431 return bRet;
434 //--------------------------------------------------------------------
435 void RegOptionsImpl::markSessionDone( )
437 OSL_ENSURE( !s_bThisSessionDone, "RegOptionsImpl::markSessionDone: already marked!" );
438 OSL_ENSURE( implGetDialogPermission( ) != RegOptions::dpDisabled, "RegOptionsImpl::markSessionDone: invalid call!" );
439 if ( !s_bThisSessionDone )
441 RegOptions::DialogPermission eOldPermission = implGetDialogPermission( );
443 s_bThisSessionDone = sal_True;
445 if ( RegOptions::dpRemindLater == eOldPermission )
446 { // no action required. If we shall remind later, the counter is already at 1, we should not change this,
447 // as the next smaller number (which is 0 :) means that the dialog would be disabled
448 OSL_ENSURE( 1 == m_nDialogCounter, "RegOptionsImpl::markSessionDone: invalid session counter (1)!" );
450 else
452 OSL_ENSURE( m_nDialogCounter > 0, "RegOptionsImpl::markSessionDone: invalid session counter (2)!" );
453 --m_nDialogCounter;
455 // decrease the session counter
456 m_aRegistrationNode.setNodeValue(
457 lcl_getRequestDialogName(),
458 makeAny( (sal_Int32)m_nDialogCounter )
461 // and clear the reminder date
462 removeReminder();
467 //====================================================================
468 //= RegOptions
469 //====================================================================
470 //--------------------------------------------------------------------
471 RegOptions::RegOptions()
472 :m_pImpl( NULL )
476 //--------------------------------------------------------------------
477 void RegOptions::ensureImpl( )
479 if ( !m_pImpl )
480 m_pImpl = RegOptionsImpl::registerClient();
483 //--------------------------------------------------------------------
484 RegOptions::~RegOptions()
486 if ( m_pImpl )
488 RegOptionsImpl::revokeClient();
489 m_pImpl = NULL;
493 //--------------------------------------------------------------------
494 String RegOptions::getRegistrationURL( ) const
496 const_cast< RegOptions* >( this )->ensureImpl( );
497 return m_pImpl->getRegistrationURL();
500 //--------------------------------------------------------------------
501 RegOptions::DialogPermission RegOptions::getDialogPermission( ) const
503 const_cast< RegOptions* >( this )->ensureImpl( );
504 return m_pImpl->getDialogPermission();
507 //--------------------------------------------------------------------
508 void RegOptions::markSessionDone( )
510 const_cast< RegOptions* >( this )->ensureImpl( );
511 m_pImpl->markSessionDone();
514 //--------------------------------------------------------------------
515 void RegOptions::activateReminder( sal_Int32 _nDaysFromNow )
517 const_cast< RegOptions* >( this )->ensureImpl( );
518 m_pImpl->activateReminder( _nDaysFromNow );
521 //--------------------------------------------------------------------
522 sal_Bool RegOptions::allowMenu( ) const
524 /// we cache this setting, 'cause it is needed very often
525 static sal_Bool bKnowMenuPermission = sal_False;
526 static sal_Bool bAllowMenu = sal_False;
528 if ( !bKnowMenuPermission )
530 const_cast< RegOptions* >( this )->ensureImpl( );
531 bAllowMenu = m_pImpl->allowMenu();
532 bKnowMenuPermission = sal_True;
534 return bAllowMenu;
537 //--------------------------------------------------------------------
538 void RegOptions::removeReminder()
540 const_cast< RegOptions* >( this )->ensureImpl( );
541 m_pImpl->removeReminder();
544 //--------------------------------------------------------------------
545 bool RegOptions::hasReminderDateCome() const
547 const_cast< RegOptions* >( this )->ensureImpl( );
548 return m_pImpl->hasReminderDateCome();
551 //........................................................................
552 } // namespace svt
553 //........................................................................