fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / scripting / source / stringresource / stringresource.cxx
blob0c64fa2b688029f13e58e6557c15a6fc2179a9ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "stringresource.hxx"
21 #include <com/sun/star/io/TempFile.hpp>
22 #include <com/sun/star/io/TextInputStream.hpp>
23 #include <com/sun/star/io/TextOutputStream.hpp>
24 #include <com/sun/star/io/XActiveDataSink.hpp>
25 #include <com/sun/star/io/XActiveDataSource.hpp>
26 #include <com/sun/star/io/XStream.hpp>
27 #include <com/sun/star/io/XSeekable.hpp>
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
30 #include <cppuhelper/implementationentry.hxx>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
36 #include <rtl/tencinfo.h>
37 #include <rtl/ustrbuf.hxx>
38 #include <rtl/strbuf.hxx>
39 #include <tools/urlobj.hxx>
40 #include <i18nlangtag/languagetag.hxx>
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::lang;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::ucb;
46 using namespace ::com::sun::star::util;
47 using namespace ::com::sun::star::embed;
48 using namespace ::com::sun::star::container;
52 namespace stringresource
57 // mutex
60 ::osl::Mutex& getMutex()
62 static ::osl::Mutex* s_pMutex = 0;
63 if ( !s_pMutex )
65 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
66 if ( !s_pMutex )
68 static ::osl::Mutex s_aMutex;
69 s_pMutex = &s_aMutex;
72 return *s_pMutex;
77 // StringResourceImpl
80 // component operations
81 static Sequence< OUString > getSupportedServiceNames_StringResourceImpl()
83 Sequence< OUString > names(1);
84 names[0] = "com.sun.star.resource.StringResource";
85 return names;
88 static OUString getImplementationName_StringResourceImpl()
90 return OUString( "com.sun.star.comp.scripting.StringResource" );
93 static Reference< XInterface > SAL_CALL create_StringResourceImpl(
94 Reference< XComponentContext > const & xContext )
96 return static_cast< ::cppu::OWeakObject * >( new StringResourcePersistenceImpl( xContext ) );
102 StringResourceImpl::StringResourceImpl( const Reference< XComponentContext >& rxContext )
103 : m_xContext( rxContext )
104 , m_pCurrentLocaleItem( NULL )
105 , m_pDefaultLocaleItem( NULL )
106 , m_bDefaultModified( false )
107 , m_aListenerContainer( getMutex() )
108 , m_bModified( false )
109 , m_bReadOnly( false )
110 , m_nNextUniqueNumericId( UNIQUE_NUMBER_NEEDS_INITIALISATION )
116 StringResourceImpl::~StringResourceImpl()
118 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
120 LocaleItem* pLocaleItem = *it;
121 delete pLocaleItem;
124 for( LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin(); it != m_aDeletedLocaleItemVector.end(); ++it )
126 LocaleItem* pLocaleItem = *it;
127 delete pLocaleItem;
133 // XServiceInfo
135 OUString StringResourceImpl::getImplementationName( ) throw (RuntimeException, std::exception)
137 return getImplementationName_StringResourceImpl();
140 sal_Bool StringResourceImpl::supportsService( const OUString& rServiceName ) throw (RuntimeException, std::exception)
142 return cppu::supportsService(this, rServiceName);
145 Sequence< OUString > StringResourceImpl::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
147 return getSupportedServiceNames_StringResourceImpl();
152 // XModifyBroadcaster
154 void StringResourceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
155 throw (RuntimeException, std::exception)
157 if( !aListener.is() )
158 throw RuntimeException();
160 ::osl::MutexGuard aGuard( getMutex() );
161 m_aListenerContainer.addInterface( Reference<XInterface>( aListener, UNO_QUERY ) );
164 void StringResourceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
165 throw (RuntimeException, std::exception)
167 if( !aListener.is() )
168 throw RuntimeException();
170 ::osl::MutexGuard aGuard( getMutex() );
171 m_aListenerContainer.removeInterface( Reference<XInterface>( aListener, UNO_QUERY ) );
176 // XStringResourceResolver
178 OUString StringResourceImpl::implResolveString
179 ( const OUString& ResourceID, LocaleItem* pLocaleItem )
180 throw (::com::sun::star::resource::MissingResourceException)
182 OUString aRetStr;
183 bool bSuccess = false;
184 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
186 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
187 if( !( it == pLocaleItem->m_aIdToStringMap.end() ) )
189 aRetStr = (*it).second;
190 bSuccess = true;
193 if( !bSuccess )
195 OUString errorMsg("StringResourceImpl: No entry for ResourceID: ");
196 errorMsg = errorMsg.concat( ResourceID );
197 throw ::com::sun::star::resource::MissingResourceException( errorMsg );
199 return aRetStr;
202 OUString StringResourceImpl::resolveString( const OUString& ResourceID )
203 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
205 ::osl::MutexGuard aGuard( getMutex() );
206 return implResolveString( ResourceID, m_pCurrentLocaleItem );
209 OUString StringResourceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
210 throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
212 ::osl::MutexGuard aGuard( getMutex() );
213 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
214 return implResolveString( ResourceID, pLocaleItem );
217 bool StringResourceImpl::implHasEntryForId( const OUString& ResourceID, LocaleItem* pLocaleItem )
219 bool bSuccess = false;
220 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
222 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
223 if( !( it == pLocaleItem->m_aIdToStringMap.end() ) )
224 bSuccess = true;
226 return bSuccess;
229 sal_Bool StringResourceImpl::hasEntryForId( const OUString& ResourceID )
230 throw (RuntimeException, std::exception)
232 ::osl::MutexGuard aGuard( getMutex() );
233 return implHasEntryForId( ResourceID, m_pCurrentLocaleItem );
236 sal_Bool StringResourceImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
237 const Locale& locale )
238 throw (RuntimeException, std::exception)
240 ::osl::MutexGuard aGuard( getMutex() );
241 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
242 return implHasEntryForId( ResourceID, pLocaleItem );
245 Sequence< OUString > StringResourceImpl::implGetResourceIDs( LocaleItem* pLocaleItem )
247 Sequence< OUString > aIDSeq( 0 );
248 if( pLocaleItem && loadLocale( pLocaleItem ) )
250 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
251 sal_Int32 nResourceIDCount = rHashMap.size();
252 aIDSeq.realloc( nResourceIDCount );
253 OUString* pStrings = aIDSeq.getArray();
255 IdToStringMap::const_iterator it;
256 int iTarget = 0;
257 for( it = rHashMap.begin(); it != rHashMap.end(); ++it )
259 OUString aStr = (*it).first;
260 pStrings[iTarget] = aStr;
261 iTarget++;
264 return aIDSeq;
267 Sequence< OUString > StringResourceImpl::getResourceIDsForLocale
268 ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException, std::exception)
270 ::osl::MutexGuard aGuard( getMutex() );
271 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
272 return implGetResourceIDs( pLocaleItem );
275 Sequence< OUString > StringResourceImpl::getResourceIDs( )
276 throw (RuntimeException, std::exception)
278 ::osl::MutexGuard aGuard( getMutex() );
279 return implGetResourceIDs( m_pCurrentLocaleItem );
282 Locale StringResourceImpl::getCurrentLocale()
283 throw (RuntimeException, std::exception)
285 ::osl::MutexGuard aGuard( getMutex() );
287 Locale aRetLocale;
288 if( m_pCurrentLocaleItem != NULL )
289 aRetLocale = m_pCurrentLocaleItem->m_locale;
290 return aRetLocale;
293 Locale StringResourceImpl::getDefaultLocale( )
294 throw (RuntimeException, std::exception)
296 ::osl::MutexGuard aGuard( getMutex() );
298 Locale aRetLocale;
299 if( m_pDefaultLocaleItem != NULL )
300 aRetLocale = m_pDefaultLocaleItem->m_locale;
301 return aRetLocale;
304 Sequence< Locale > StringResourceImpl::getLocales( )
305 throw (RuntimeException, std::exception)
307 ::osl::MutexGuard aGuard( getMutex() );
309 sal_Int32 nSize = m_aLocaleItemVector.size();
310 Sequence< Locale > aLocalSeq( nSize );
311 Locale* pLocales = aLocalSeq.getArray();
312 int iTarget = 0;
313 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
315 LocaleItem* pLocaleItem = *it;
316 pLocales[iTarget] = pLocaleItem->m_locale;
317 iTarget++;
319 return aLocalSeq;
324 // XStringResourceManager
326 void StringResourceImpl::implCheckReadOnly( const sal_Char* pExceptionMsg )
327 throw (NoSupportException)
329 if( m_bReadOnly )
331 OUString errorMsg = OUString::createFromAscii( pExceptionMsg );
332 throw NoSupportException( errorMsg );
336 sal_Bool StringResourceImpl::isReadOnly()
337 throw (RuntimeException, std::exception)
339 return m_bReadOnly;
342 void StringResourceImpl::implSetCurrentLocale( const Locale& locale,
343 bool FindClosestMatch, bool bUseDefaultIfNoMatch )
344 throw (IllegalArgumentException, RuntimeException)
346 ::osl::MutexGuard aGuard( getMutex() );
348 LocaleItem* pLocaleItem = NULL;
349 if( FindClosestMatch )
350 pLocaleItem = getClosestMatchItemForLocale( locale );
351 else
352 pLocaleItem = getItemForLocale( locale, true );
354 if( pLocaleItem == NULL && bUseDefaultIfNoMatch )
355 pLocaleItem = m_pDefaultLocaleItem;
357 if( pLocaleItem != NULL )
359 (void)loadLocale( pLocaleItem );
360 m_pCurrentLocaleItem = pLocaleItem;
362 // Only notify without modifying
363 implNotifyListeners();
367 void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
368 throw (IllegalArgumentException, RuntimeException, std::exception)
370 bool bUseDefaultIfNoMatch = false;
371 implSetCurrentLocale( locale, FindClosestMatch, bUseDefaultIfNoMatch );
374 void StringResourceImpl::setDefaultLocale( const Locale& locale )
375 throw (IllegalArgumentException, RuntimeException,NoSupportException, std::exception)
377 ::osl::MutexGuard aGuard( getMutex() );
378 implCheckReadOnly( "StringResourceImpl::setDefaultLocale(): Read only" );
380 LocaleItem* pLocaleItem = getItemForLocale( locale, true );
381 if( pLocaleItem && pLocaleItem != m_pDefaultLocaleItem )
383 if( m_pDefaultLocaleItem )
385 LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale );
386 m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem );
389 m_pDefaultLocaleItem = pLocaleItem;
390 m_bDefaultModified = true;
391 implModified();
395 void StringResourceImpl::implSetString( const OUString& ResourceID,
396 const OUString& Str, LocaleItem* pLocaleItem )
398 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
400 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
402 IdToStringMap::iterator it = rHashMap.find( ResourceID );
403 bool bNew = ( it == rHashMap.end() );
404 if( bNew )
406 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
407 rIndexMap[ ResourceID ] = pLocaleItem->m_nNextIndex++;
408 implScanIdForNumber( ResourceID );
410 rHashMap[ ResourceID ] = Str;
411 pLocaleItem->m_bModified = true;
412 implModified();
416 void StringResourceImpl::setString( const OUString& ResourceID, const OUString& Str )
417 throw (NoSupportException, RuntimeException, std::exception)
419 ::osl::MutexGuard aGuard( getMutex() );
420 implCheckReadOnly( "StringResourceImpl::setString(): Read only" );
421 implSetString( ResourceID, Str, m_pCurrentLocaleItem );
424 void StringResourceImpl::setStringForLocale
425 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
426 throw (NoSupportException, RuntimeException, std::exception)
428 ::osl::MutexGuard aGuard( getMutex() );
429 implCheckReadOnly( "StringResourceImpl::setStringForLocale(): Read only" );
430 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
431 implSetString( ResourceID, Str, pLocaleItem );
434 void StringResourceImpl::implRemoveId( const OUString& ResourceID, LocaleItem* pLocaleItem )
435 throw (::com::sun::star::resource::MissingResourceException)
437 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
439 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
440 IdToStringMap::iterator it = rHashMap.find( ResourceID );
441 if( it == rHashMap.end() )
443 OUString errorMsg("StringResourceImpl: No entries for ResourceID: ");
444 errorMsg = errorMsg.concat( ResourceID );
445 throw ::com::sun::star::resource::MissingResourceException( errorMsg );
447 rHashMap.erase( it );
448 pLocaleItem->m_bModified = true;
449 implModified();
453 void StringResourceImpl::removeId( const OUString& ResourceID )
454 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
456 ::osl::MutexGuard aGuard( getMutex() );
457 implCheckReadOnly( "StringResourceImpl::removeId(): Read only" );
458 implRemoveId( ResourceID, m_pCurrentLocaleItem );
461 void StringResourceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
462 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
464 ::osl::MutexGuard aGuard( getMutex() );
465 implCheckReadOnly( "StringResourceImpl::removeIdForLocale(): Read only" );
466 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
467 implRemoveId( ResourceID, pLocaleItem );
470 void StringResourceImpl::newLocale( const Locale& locale )
471 throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
473 ::osl::MutexGuard aGuard( getMutex() );
474 implCheckReadOnly( "StringResourceImpl::newLocale(): Read only" );
476 if( getItemForLocale( locale, false ) != NULL )
478 OUString errorMsg("StringResourceImpl: locale already exists");
479 throw ElementExistException( errorMsg );
482 // TODO?: Check if locale is valid? How?
483 //if (!bValid)
485 // OUString errorMsg("StringResourceImpl: Invalid locale");
486 // throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
489 LocaleItem* pLocaleItem = new LocaleItem( locale );
490 m_aLocaleItemVector.push_back( pLocaleItem );
491 pLocaleItem->m_bModified = true;
493 // Copy strings from default locale
494 LocaleItem* pCopyFromItem = m_pDefaultLocaleItem;
495 if( pCopyFromItem == NULL )
496 pCopyFromItem = m_pCurrentLocaleItem;
497 if( pCopyFromItem != NULL && loadLocale( pCopyFromItem ) )
499 const IdToStringMap& rSourceMap = pCopyFromItem->m_aIdToStringMap;
500 IdToStringMap& rTargetMap = pLocaleItem->m_aIdToStringMap;
501 IdToStringMap::const_iterator it;
502 for( it = rSourceMap.begin(); it != rSourceMap.end(); ++it )
504 OUString aId = (*it).first;
505 OUString aStr = (*it).second;
506 rTargetMap[ aId ] = aStr;
509 const IdToIndexMap& rSourceIndexMap = pCopyFromItem->m_aIdToIndexMap;
510 IdToIndexMap& rTargetIndexMap = pLocaleItem->m_aIdToIndexMap;
511 IdToIndexMap::const_iterator it_index;
512 for( it_index = rSourceIndexMap.begin(); it_index != rSourceIndexMap.end(); ++it_index )
514 OUString aId = (*it_index).first;
515 sal_Int32 nIndex = (*it_index).second;
516 rTargetIndexMap[ aId ] = nIndex;
518 pLocaleItem->m_nNextIndex = pCopyFromItem->m_nNextIndex;
521 if( m_pCurrentLocaleItem == NULL )
522 m_pCurrentLocaleItem = pLocaleItem;
524 if( m_pDefaultLocaleItem == NULL )
526 m_pDefaultLocaleItem = pLocaleItem;
527 m_bDefaultModified = true;
530 implModified();
533 void StringResourceImpl::removeLocale( const Locale& locale )
534 throw (IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
536 ::osl::MutexGuard aGuard( getMutex() );
537 implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" );
539 LocaleItem* pRemoveItem = getItemForLocale( locale, true );
540 if( pRemoveItem )
542 // Last locale?
543 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
544 if( nLocaleCount > 1 )
546 if( m_pCurrentLocaleItem == pRemoveItem ||
547 m_pDefaultLocaleItem == pRemoveItem )
549 LocaleItem* pFallbackItem = NULL;
550 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
552 LocaleItem* pLocaleItem = *it;
553 if( pLocaleItem != pRemoveItem )
555 pFallbackItem = pLocaleItem;
556 break;
559 if( m_pCurrentLocaleItem == pRemoveItem )
561 bool FindClosestMatch = false;
562 setCurrentLocale( pFallbackItem->m_locale, FindClosestMatch );
564 if( m_pDefaultLocaleItem == pRemoveItem )
566 setDefaultLocale( pFallbackItem->m_locale );
570 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
572 LocaleItem* pLocaleItem = *it;
573 if( pLocaleItem == pRemoveItem )
575 // Remember locale item to delete file while storing
576 m_aDeletedLocaleItemVector.push_back( pLocaleItem );
578 // Last locale?
579 if( nLocaleCount == 1 )
581 m_nNextUniqueNumericId = 0;
582 if( m_pDefaultLocaleItem )
584 LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale );
585 m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem );
587 m_pCurrentLocaleItem = NULL;
588 m_pDefaultLocaleItem = NULL;
591 m_aLocaleItemVector.erase( it );
593 implModified();
594 break;
600 void StringResourceImpl::implScanIdForNumber( const OUString& ResourceID )
602 const sal_Unicode* pSrc = ResourceID.getStr();
603 sal_Int32 nLen = ResourceID.getLength();
605 sal_Int32 nNumber = 0;
606 for( sal_Int32 i = 0 ; i < nLen ; i++ )
608 sal_Unicode c = pSrc[i];
609 if( c >= '0' && c <= '9' )
611 sal_uInt16 nDigitVal = c - '0';
612 nNumber = 10*nNumber + nDigitVal;
614 else
615 break;
618 if( m_nNextUniqueNumericId < nNumber + 1 )
619 m_nNextUniqueNumericId = nNumber + 1;
622 sal_Int32 StringResourceImpl::getUniqueNumericId( )
623 throw (RuntimeException, NoSupportException, std::exception)
625 if( m_nNextUniqueNumericId == UNIQUE_NUMBER_NEEDS_INITIALISATION )
627 implLoadAllLocales();
628 m_nNextUniqueNumericId = 0;
631 if( m_nNextUniqueNumericId < UNIQUE_NUMBER_NEEDS_INITIALISATION )
633 OUString errorMsg("getUniqueNumericId: Extended sal_Int32 range");
634 throw NoSupportException( errorMsg );
636 return m_nNextUniqueNumericId;
641 // Private helper methods
643 LocaleItem* StringResourceImpl::getItemForLocale
644 ( const Locale& locale, bool bException )
645 throw (::com::sun::star::lang::IllegalArgumentException)
647 LocaleItem* pRetItem = NULL;
649 // Search for locale
650 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
652 LocaleItem* pLocaleItem = *it;
653 if( pLocaleItem )
655 Locale& cmp_locale = pLocaleItem->m_locale;
656 if( cmp_locale.Language == locale.Language &&
657 cmp_locale.Country == locale.Country &&
658 cmp_locale.Variant == locale.Variant )
660 pRetItem = pLocaleItem;
661 break;
666 if( pRetItem == NULL && bException )
668 OUString errorMsg("StringResourceImpl: Invalid locale");
669 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
671 return pRetItem;
674 // Returns the LocaleItem for a given locale, if it exists, otherwise NULL.
675 // This method performs a closest match search, at least the language must match.
676 LocaleItem* StringResourceImpl::getClosestMatchItemForLocale( const Locale& locale )
678 LocaleItem* pRetItem = NULL;
680 ::std::vector< Locale > aLocales( m_aLocaleItemVector.size());
681 size_t i = 0;
682 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it, ++i )
684 LocaleItem* pLocaleItem = *it;
685 aLocales[i] = (pLocaleItem ? pLocaleItem->m_locale : Locale());
687 ::std::vector< Locale >::const_iterator iFound( LanguageTag::getMatchingFallback( aLocales, locale));
688 if (iFound != aLocales.end())
689 pRetItem = *(m_aLocaleItemVector.begin() + (iFound - aLocales.begin()));
691 return pRetItem;
694 void StringResourceImpl::implModified()
696 m_bModified = true;
697 implNotifyListeners();
700 void StringResourceImpl::implNotifyListeners()
702 EventObject aEvent;
703 aEvent.Source = static_cast< XInterface* >( (OWeakObject*)this );
705 ::cppu::OInterfaceIteratorHelper it( m_aListenerContainer );
706 while( it.hasMoreElements() )
708 Reference< XInterface > xIface = it.next();
709 Reference< XModifyListener > xListener( xIface, UNO_QUERY );
712 xListener->modified( aEvent );
714 catch(RuntimeException&)
716 it.remove();
723 // Loading
725 bool StringResourceImpl::loadLocale( LocaleItem* pLocaleItem )
727 // Base implementation has nothing to load
728 (void)pLocaleItem;
729 return true;
732 void StringResourceImpl::implLoadAllLocales()
734 // Base implementation has nothing to load
738 Reference< XMultiComponentFactory > StringResourceImpl::getMultiComponentFactory()
740 ::osl::MutexGuard aGuard( getMutex() );
742 if( !m_xMCF.is() )
744 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
745 if( !xSMgr.is() )
747 throw RuntimeException(
748 "StringResourceImpl::getMultiComponentFactory: Couldn't instantiate MultiComponentFactory" );
750 m_xMCF = xSMgr;
752 return m_xMCF;
757 // StringResourcePersistenceImpl
760 StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext )
761 : StringResourcePersistenceImpl_BASE( rxContext )
767 StringResourcePersistenceImpl::~StringResourcePersistenceImpl()
772 // XServiceInfo
775 OUString StringResourcePersistenceImpl::getImplementationName( )
776 throw (RuntimeException, std::exception)
778 return OUString( "com.sun.star.comp.scripting.StringResource");
783 sal_Bool StringResourcePersistenceImpl::supportsService( const OUString& rServiceName )
784 throw (RuntimeException, std::exception)
786 return cppu::supportsService( this, rServiceName );
791 Sequence< OUString > StringResourcePersistenceImpl::getSupportedServiceNames( )
792 throw (RuntimeException, std::exception)
794 return StringResourceImpl::getSupportedServiceNames();
798 // XInitialization base functionality for derived classes
801 static const char aNameBaseDefaultStr[] = "strings";
803 void StringResourcePersistenceImpl::implInitializeCommonParameters
804 ( const Sequence< Any >& aArguments )
805 throw (Exception, RuntimeException)
807 bool bReadOnlyOk = (aArguments[1] >>= m_bReadOnly);
808 if( !bReadOnlyOk )
810 OUString errorMsg("XInitialization::initialize: Expected ReadOnly flag");
811 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 1 );
814 com::sun::star::lang::Locale aCurrentLocale;
815 bool bLocaleOk = (aArguments[2] >>= aCurrentLocale);
816 if( !bLocaleOk )
818 OUString errorMsg("XInitialization::initialize: Expected Locale");
819 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 2 );
822 bool bNameBaseOk = (aArguments[3] >>= m_aNameBase);
823 if( !bNameBaseOk )
825 OUString errorMsg("XInitialization::initialize: Expected NameBase string");
826 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 3 );
828 if( m_aNameBase.isEmpty() )
829 m_aNameBase = aNameBaseDefaultStr;
831 bool bCommentOk = (aArguments[4] >>= m_aComment);
832 if( !bCommentOk )
834 OUString errorMsg("XInitialization::initialize: Expected Comment string");
835 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 4 );
838 implScanLocales();
840 bool FindClosestMatch = true;
841 bool bUseDefaultIfNoMatch = true;
842 implSetCurrentLocale( aCurrentLocale, FindClosestMatch, bUseDefaultIfNoMatch );
846 // Forwarding calls to base class
848 // XModifyBroadcaster
849 void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
850 throw (RuntimeException, std::exception)
852 StringResourceImpl::addModifyListener( aListener );
854 void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
855 throw (RuntimeException, std::exception)
857 StringResourceImpl::removeModifyListener( aListener );
860 // XStringResourceResolver
861 OUString StringResourcePersistenceImpl::resolveString( const OUString& ResourceID )
862 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
864 return StringResourceImpl::resolveString( ResourceID ) ;
866 OUString StringResourcePersistenceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
867 throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
869 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
871 sal_Bool StringResourcePersistenceImpl::hasEntryForId( const OUString& ResourceID )
872 throw (RuntimeException, std::exception)
874 return StringResourceImpl::hasEntryForId( ResourceID ) ;
876 sal_Bool StringResourcePersistenceImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
877 const Locale& locale )
878 throw (RuntimeException, std::exception)
880 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
882 Locale StringResourcePersistenceImpl::getCurrentLocale()
883 throw (RuntimeException, std::exception)
885 return StringResourceImpl::getCurrentLocale();
887 Locale StringResourcePersistenceImpl::getDefaultLocale( )
888 throw (RuntimeException, std::exception)
890 return StringResourceImpl::getDefaultLocale();
892 Sequence< Locale > StringResourcePersistenceImpl::getLocales( )
893 throw (RuntimeException, std::exception)
895 return StringResourceImpl::getLocales();
898 // XStringResourceManager
899 sal_Bool StringResourcePersistenceImpl::isReadOnly()
900 throw (RuntimeException, std::exception)
902 return StringResourceImpl::isReadOnly();
904 void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
905 throw (IllegalArgumentException, RuntimeException, std::exception)
907 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
909 void StringResourcePersistenceImpl::setDefaultLocale( const Locale& locale )
910 throw (IllegalArgumentException, RuntimeException,NoSupportException, std::exception)
912 StringResourceImpl::setDefaultLocale( locale );
914 Sequence< OUString > StringResourcePersistenceImpl::getResourceIDs( )
915 throw (RuntimeException, std::exception)
917 return StringResourceImpl::getResourceIDs();
919 void StringResourcePersistenceImpl::setString( const OUString& ResourceID, const OUString& Str )
920 throw (NoSupportException, RuntimeException, std::exception)
922 StringResourceImpl::setString( ResourceID, Str );
924 void StringResourcePersistenceImpl::setStringForLocale
925 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
926 throw (NoSupportException, RuntimeException, std::exception)
928 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
930 Sequence< OUString > StringResourcePersistenceImpl::getResourceIDsForLocale
931 ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException, std::exception)
933 return StringResourceImpl::getResourceIDsForLocale( locale );
935 void StringResourcePersistenceImpl::removeId( const OUString& ResourceID )
936 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
938 StringResourceImpl::removeId( ResourceID );
940 void StringResourcePersistenceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
941 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
943 StringResourceImpl::removeIdForLocale( ResourceID, locale );
945 void StringResourcePersistenceImpl::newLocale( const Locale& locale )
946 throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
948 StringResourceImpl::newLocale( locale );
950 void StringResourcePersistenceImpl::removeLocale( const Locale& locale )
951 throw (IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
953 StringResourceImpl::removeLocale( locale );
955 sal_Int32 StringResourcePersistenceImpl::getUniqueNumericId( )
956 throw (RuntimeException, NoSupportException, std::exception)
958 return StringResourceImpl::getUniqueNumericId();
962 // XStringResourcePersistence
964 void StringResourcePersistenceImpl::store()
965 throw (NoSupportException, Exception, RuntimeException, std::exception)
969 sal_Bool StringResourcePersistenceImpl::isModified( )
970 throw (RuntimeException, std::exception)
972 ::osl::MutexGuard aGuard( getMutex() );
974 return m_bModified;
977 void StringResourcePersistenceImpl::setComment( const OUString& Comment )
978 throw (::com::sun::star::uno::RuntimeException, std::exception)
980 m_aComment = Comment;
983 void StringResourcePersistenceImpl::storeToStorage( const Reference< XStorage >& Storage,
984 const OUString& NameBase, const OUString& Comment )
985 throw (Exception, RuntimeException, std::exception)
987 ::osl::MutexGuard aGuard( getMutex() );
989 bool bUsedForStore = false;
990 bool bStoreAll = true;
991 implStoreAtStorage( NameBase, Comment, Storage, bUsedForStore, bStoreAll );
994 void StringResourcePersistenceImpl::implStoreAtStorage
996 const OUString& aNameBase,
997 const OUString& aComment,
998 const Reference< ::com::sun::star::embed::XStorage >& Storage,
999 bool bUsedForStore,
1000 bool bStoreAll
1002 throw (Exception, RuntimeException)
1004 // Delete files for deleted locales
1005 if( bUsedForStore )
1007 while( m_aDeletedLocaleItemVector.size() > 0 )
1009 LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin();
1010 LocaleItem* pLocaleItem = *it;
1011 if( pLocaleItem != NULL )
1013 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
1014 aStreamName += ".properties";
1018 Storage->removeElement( aStreamName );
1020 catch( Exception& )
1023 m_aDeletedLocaleItemVector.erase( it );
1024 delete pLocaleItem;
1029 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
1031 LocaleItem* pLocaleItem = *it;
1032 if( pLocaleItem != NULL && (bStoreAll || pLocaleItem->m_bModified) &&
1033 loadLocale( pLocaleItem ) )
1035 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1036 aStreamName += ".properties";
1038 Reference< io::XStream > xElementStream =
1039 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
1041 OUString aPropName("MediaType");
1042 OUString aMime("text/plain");
1044 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
1045 OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!\n" );
1046 if ( xProps.is() )
1048 xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
1050 aPropName = "UseCommonStoragePasswordEncryption";
1051 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) );
1054 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
1055 if( xOutputStream.is() )
1056 implWritePropertiesFile( pLocaleItem, xOutputStream, aComment );
1057 xOutputStream->closeOutput();
1059 if( bUsedForStore )
1060 pLocaleItem->m_bModified = false;
1064 // Delete files for changed defaults
1065 if( bUsedForStore )
1067 for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin();
1068 it != m_aChangedDefaultLocaleVector.end(); ++it )
1070 LocaleItem* pLocaleItem = *it;
1071 if( pLocaleItem != NULL )
1073 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
1074 aStreamName += ".default";
1078 Storage->removeElement( aStreamName );
1080 catch( Exception& )
1083 delete pLocaleItem;
1086 m_aChangedDefaultLocaleVector.clear();
1089 // Default locale
1090 if( m_pDefaultLocaleItem != NULL && (bStoreAll || m_bDefaultModified) )
1092 OUString aStreamName = implGetFileNameForLocaleItem( m_pDefaultLocaleItem, aNameBase );
1093 aStreamName += ".default";
1095 Reference< io::XStream > xElementStream =
1096 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
1098 // Only create stream without content
1099 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
1100 xOutputStream->closeOutput();
1102 if( bUsedForStore )
1103 m_bDefaultModified = false;
1107 void StringResourcePersistenceImpl::storeToURL( const OUString& URL,
1108 const OUString& NameBase, const OUString& Comment,
1109 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
1110 throw (Exception, RuntimeException, std::exception)
1112 ::osl::MutexGuard aGuard( getMutex() );
1114 bool bUsedForStore = false;
1115 bool bStoreAll = true;
1117 Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create(m_xContext);
1118 if( xFileAccess.is() && Handler.is() )
1119 xFileAccess->setInteractionHandler( Handler );
1121 implStoreAtLocation( URL, NameBase, Comment, xFileAccess, bUsedForStore, bStoreAll );
1124 void StringResourcePersistenceImpl::implKillRemovedLocaleFiles
1126 const OUString& Location,
1127 const OUString& aNameBase,
1128 const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess3 >& xFileAccess
1130 throw (Exception, RuntimeException)
1132 // Delete files for deleted locales
1133 while( m_aDeletedLocaleItemVector.size() > 0 )
1135 LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin();
1136 LocaleItem* pLocaleItem = *it;
1137 if( pLocaleItem != NULL )
1139 OUString aCompleteFileName =
1140 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location );
1141 if( xFileAccess->exists( aCompleteFileName ) )
1142 xFileAccess->kill( aCompleteFileName );
1144 m_aDeletedLocaleItemVector.erase( it );
1145 delete pLocaleItem;
1150 void StringResourcePersistenceImpl::implKillChangedDefaultFiles
1152 const OUString& Location,
1153 const OUString& aNameBase,
1154 const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess3 >& xFileAccess
1156 throw (Exception, RuntimeException)
1158 // Delete files for changed defaults
1159 for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin();
1160 it != m_aChangedDefaultLocaleVector.end(); ++it )
1162 LocaleItem* pLocaleItem = *it;
1163 if( pLocaleItem != NULL )
1165 OUString aCompleteFileName =
1166 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location, true );
1167 if( xFileAccess->exists( aCompleteFileName ) )
1168 xFileAccess->kill( aCompleteFileName );
1170 delete pLocaleItem;
1173 m_aChangedDefaultLocaleVector.clear();
1176 void StringResourcePersistenceImpl::implStoreAtLocation
1178 const OUString& Location,
1179 const OUString& aNameBase,
1180 const OUString& aComment,
1181 const Reference< ucb::XSimpleFileAccess3 >& xFileAccess,
1182 bool bUsedForStore,
1183 bool bStoreAll,
1184 bool bKillAll
1186 throw (Exception, RuntimeException)
1188 // Delete files for deleted locales
1189 if( bUsedForStore || bKillAll )
1190 implKillRemovedLocaleFiles( Location, aNameBase, xFileAccess );
1192 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
1194 LocaleItem* pLocaleItem = *it;
1195 if( pLocaleItem != NULL && (bStoreAll || bKillAll || pLocaleItem->m_bModified) &&
1196 loadLocale( pLocaleItem ) )
1198 OUString aCompleteFileName =
1199 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location );
1200 if( xFileAccess->exists( aCompleteFileName ) )
1201 xFileAccess->kill( aCompleteFileName );
1203 if( !bKillAll )
1205 // Create Output stream
1206 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1207 if( xOutputStream.is() )
1209 implWritePropertiesFile( pLocaleItem, xOutputStream, aComment );
1210 xOutputStream->closeOutput();
1212 if( bUsedForStore )
1213 pLocaleItem->m_bModified = false;
1218 // Delete files for changed defaults
1219 if( bUsedForStore || bKillAll )
1220 implKillChangedDefaultFiles( Location, aNameBase, xFileAccess );
1222 // Default locale
1223 if( m_pDefaultLocaleItem != NULL && (bStoreAll || bKillAll || m_bDefaultModified) )
1225 OUString aCompleteFileName =
1226 implGetPathForLocaleItem( m_pDefaultLocaleItem, aNameBase, Location, true );
1227 if( xFileAccess->exists( aCompleteFileName ) )
1228 xFileAccess->kill( aCompleteFileName );
1230 if( !bKillAll )
1232 // Create Output stream
1233 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1234 if( xOutputStream.is() )
1235 xOutputStream->closeOutput();
1237 if( bUsedForStore )
1238 m_bDefaultModified = false;
1245 // BinaryOutput, helper class for exportBinary
1247 class BinaryOutput
1249 Reference< XMultiComponentFactory > m_xMCF;
1250 Reference< XComponentContext > m_xContext;
1251 Reference< XInterface > m_xTempFile;
1252 Reference< io::XOutputStream > m_xOutputStream;
1254 public:
1255 BinaryOutput( Reference< XMultiComponentFactory > xMCF,
1256 Reference< XComponentContext > xContext );
1258 Reference< io::XOutputStream > getOutputStream() const
1259 { return m_xOutputStream; }
1261 Sequence< ::sal_Int8 > closeAndGetData();
1263 // Template to be used with sal_Int16 and sal_Unicode
1264 template< class T >
1265 void write16BitInt( T n );
1266 void writeInt16( sal_Int16 n )
1267 { write16BitInt( n ); }
1268 void writeUnicodeChar( sal_Unicode n )
1269 { write16BitInt( n ); }
1270 void writeInt32( sal_Int32 n );
1271 void writeString( const OUString& aStr );
1274 BinaryOutput::BinaryOutput( Reference< XMultiComponentFactory > xMCF,
1275 Reference< XComponentContext > xContext )
1276 : m_xMCF( xMCF )
1277 , m_xContext( xContext )
1279 m_xTempFile = io::TempFile::create( m_xContext );
1280 m_xOutputStream = Reference< io::XOutputStream >( m_xTempFile, UNO_QUERY_THROW );
1283 template< class T >
1284 void BinaryOutput::write16BitInt( T n )
1286 if( !m_xOutputStream.is() )
1287 return;
1289 Sequence< sal_Int8 > aSeq( 2 );
1290 sal_Int8* p = aSeq.getArray();
1292 sal_Int8 nLow = sal_Int8( n & 0xff );
1293 sal_Int8 nHigh = sal_Int8( n >> 8 );
1295 p[0] = nLow;
1296 p[1] = nHigh;
1297 m_xOutputStream->writeBytes( aSeq );
1300 void BinaryOutput::writeInt32( sal_Int32 n )
1302 if( !m_xOutputStream.is() )
1303 return;
1305 Sequence< sal_Int8 > aSeq( 4 );
1306 sal_Int8* p = aSeq.getArray();
1308 for( sal_Int16 i = 0 ; i < 4 ; i++ )
1310 p[i] = sal_Int8( n & 0xff );
1311 n >>= 8;
1313 m_xOutputStream->writeBytes( aSeq );
1316 void BinaryOutput::writeString( const OUString& aStr )
1318 sal_Int32 nLen = aStr.getLength();
1319 const sal_Unicode* pStr = aStr.getStr();
1321 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1322 writeUnicodeChar( pStr[i] );
1324 writeUnicodeChar( 0 );
1327 Sequence< ::sal_Int8 > BinaryOutput::closeAndGetData()
1329 Sequence< ::sal_Int8 > aRetSeq;
1330 if( !m_xOutputStream.is() )
1331 return aRetSeq;
1333 m_xOutputStream->closeOutput();
1335 Reference< io::XSeekable> xSeekable( m_xTempFile, UNO_QUERY );
1336 if( !xSeekable.is() )
1337 return aRetSeq;
1339 sal_Int32 nSize = (sal_Int32)xSeekable->getPosition();
1341 Reference< io::XInputStream> xInputStream( m_xTempFile, UNO_QUERY );
1342 if( !xInputStream.is() )
1343 return aRetSeq;
1345 xSeekable->seek( 0 );
1346 sal_Int32 nRead = xInputStream->readBytes( aRetSeq, nSize );
1347 (void)nRead;
1348 OSL_ENSURE( nRead == nSize, "BinaryOutput::closeAndGetData: nRead != nSize" );
1350 return aRetSeq;
1354 // Binary format:
1356 // Header
1357 // Byte Content
1358 // 0 + 1 sal_Int16: Version, currently 0, low byte first
1359 // 2 + 3 sal_Int16: Locale count = n, low byte first
1360 // 4 + 5 sal_Int16: Default Locale position in Locale list, == n if none
1361 // 6 - 7 sal_Int32: Start index locale block 0, lowest byte first
1362 // (n-1) * sal_Int32: Start index locale block 1 to n, lowest byte first
1363 // 6 + 4*n sal_Int32: "Start index" non existing locale block n+1,
1364 // marks the first invalid index, kind of EOF
1366 // Locale block
1367 // All strings are stored as 2-Byte-0 terminated sequence
1368 // of 16 bit Unicode characters, each with low byte first
1369 // Empty strings only contain the 2-Byte-0
1371 // Members of com.sun.star.lang.Locale
1372 // with l1 = Locale.Language.getLength()
1373 // with l2 = Locale.Country.getLength()
1374 // with l3 = Locale.Variant.getLength()
1375 // pos0 = 0 Locale.Language
1376 // pos1 = 2 * (l1 + 1) Locale.Country
1377 // pos2 = pos1 + 2 * (l2 + 1) Locale.Variant
1378 // pos3 = pos2 + 2 * (l3 + 1)
1379 // pos3 Properties file written by implWritePropertiesFile
1381 Sequence< sal_Int8 > StringResourcePersistenceImpl::exportBinary( )
1382 throw (RuntimeException, std::exception)
1384 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1385 BinaryOutput aOut( xMCF, m_xContext );
1387 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
1388 Sequence< sal_Int8 >* pLocaleDataSeq = new Sequence< sal_Int8 >[ nLocaleCount ];
1390 sal_Int32 iLocale = 0;
1391 sal_Int32 iDefault = 0;
1392 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin();
1393 it != m_aLocaleItemVector.end(); ++it,++iLocale )
1395 LocaleItem* pLocaleItem = *it;
1396 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
1398 if( m_pDefaultLocaleItem == pLocaleItem )
1399 iDefault = iLocale;
1401 BinaryOutput aLocaleOut( m_xMCF, m_xContext );
1402 implWriteLocaleBinary( pLocaleItem, aLocaleOut );
1404 pLocaleDataSeq[iLocale] = aLocaleOut.closeAndGetData();
1408 // Write header
1409 sal_Int16 nVersion = 0;
1410 sal_Int16 nLocaleCount16 = (sal_Int16)nLocaleCount;
1411 sal_Int16 iDefault16 = (sal_Int16)iDefault;
1412 aOut.writeInt16( nVersion );
1413 aOut.writeInt16( nLocaleCount16 );
1414 aOut.writeInt16( iDefault16 );
1416 // Write data positions
1417 sal_Int32 nDataPos = 6 + 4 * (nLocaleCount + 1);
1418 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1420 aOut.writeInt32( nDataPos );
1422 Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale];
1423 sal_Int32 nSeqLen = rSeq.getLength();
1424 nDataPos += nSeqLen;
1426 // Write final position
1427 aOut.writeInt32( nDataPos );
1429 // Write data
1430 Reference< io::XOutputStream > xOutputStream = aOut.getOutputStream();
1431 if( xOutputStream.is() )
1433 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1435 Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale];
1436 xOutputStream->writeBytes( rSeq );
1440 delete[] pLocaleDataSeq;
1442 Sequence< sal_Int8 > aRetSeq = aOut.closeAndGetData();
1443 return aRetSeq;
1446 void StringResourcePersistenceImpl::implWriteLocaleBinary
1447 ( LocaleItem* pLocaleItem, BinaryOutput& rOut )
1449 Reference< io::XOutputStream > xOutputStream = rOut.getOutputStream();
1450 if( !xOutputStream.is() )
1451 return;
1453 Locale& rLocale = pLocaleItem->m_locale;
1454 rOut.writeString( rLocale.Language );
1455 rOut.writeString( rLocale.Country );
1456 rOut.writeString( rLocale.Variant );
1457 implWritePropertiesFile( pLocaleItem, xOutputStream, m_aComment );
1461 // BinaryOutput, helper class for exportBinary
1463 class BinaryInput
1465 Sequence< sal_Int8 > m_aData;
1466 Reference< XMultiComponentFactory > m_xMCF;
1467 Reference< XComponentContext > m_xContext;
1469 const sal_Int8* m_pData;
1470 sal_Int32 m_nCurPos;
1471 sal_Int32 m_nSize;
1473 public:
1474 BinaryInput( const Sequence< ::sal_Int8 >& aData, Reference< XMultiComponentFactory > xMCF,
1475 Reference< XComponentContext > xContext );
1477 Reference< io::XInputStream > getInputStreamForSection( sal_Int32 nSize );
1479 void seek( sal_Int32 nPos );
1480 sal_Int32 getPosition() const
1481 { return m_nCurPos; }
1483 sal_Int16 readInt16();
1484 sal_Int32 readInt32();
1485 sal_Unicode readUnicodeChar();
1486 OUString readString();
1489 BinaryInput::BinaryInput( const Sequence< ::sal_Int8 >& aData, Reference< XMultiComponentFactory > xMCF,
1490 Reference< XComponentContext > xContext )
1491 : m_aData( aData )
1492 , m_xMCF( xMCF )
1493 , m_xContext( xContext )
1495 m_pData = m_aData.getConstArray();
1496 m_nCurPos = 0;
1497 m_nSize = m_aData.getLength();
1500 Reference< io::XInputStream > BinaryInput::getInputStreamForSection( sal_Int32 nSize )
1502 Reference< io::XInputStream > xIn;
1503 if( m_nCurPos + nSize <= m_nSize )
1505 Reference< io::XOutputStream > xTempOut( io::TempFile::create(m_xContext), UNO_QUERY_THROW );
1506 Sequence< sal_Int8 > aSection( m_pData + m_nCurPos, nSize );
1507 xTempOut->writeBytes( aSection );
1509 Reference< io::XSeekable> xSeekable( xTempOut, UNO_QUERY );
1510 if( xSeekable.is() )
1511 xSeekable->seek( 0 );
1513 xIn = Reference< io::XInputStream>( xTempOut, UNO_QUERY );
1515 else
1516 OSL_FAIL( "BinaryInput::getInputStreamForSection(): Read past end" );
1518 return xIn;
1521 void BinaryInput::seek( sal_Int32 nPos )
1523 if( nPos <= m_nSize )
1524 m_nCurPos = nPos;
1525 else
1526 OSL_FAIL( "BinaryInput::seek(): Position past end" );
1530 sal_Int16 BinaryInput::readInt16()
1532 sal_Int16 nRet = 0;
1533 if( m_nCurPos + 2 <= m_nSize )
1535 nRet = nRet + sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1536 nRet += 256 * sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1538 else
1539 OSL_FAIL( "BinaryInput::readInt16(): Read past end" );
1541 return nRet;
1544 sal_Int32 BinaryInput::readInt32()
1546 sal_Int32 nRet = 0;
1547 if( m_nCurPos + 4 <= m_nSize )
1549 sal_Int32 nFactor = 1;
1550 for( sal_Int16 i = 0; i < 4; i++ )
1552 nRet += sal_uInt8( m_pData[m_nCurPos++] ) * nFactor;
1553 nFactor *= 256;
1556 else
1557 OSL_FAIL( "BinaryInput::readInt32(): Read past end" );
1559 return nRet;
1562 sal_Unicode BinaryInput::readUnicodeChar()
1564 sal_uInt16 nRet = 0;
1565 if( m_nCurPos + 2 <= m_nSize )
1567 nRet = nRet + sal_uInt8( m_pData[m_nCurPos++] );
1568 nRet += 256 * sal_uInt8( m_pData[m_nCurPos++] );
1570 else
1571 OSL_FAIL( "BinaryInput::readUnicodeChar(): Read past end" );
1573 sal_Unicode cRet = nRet;
1574 return cRet;
1577 OUString BinaryInput::readString()
1579 OUStringBuffer aBuf;
1580 sal_Unicode c;
1583 c = readUnicodeChar();
1584 if( c != 0 )
1585 aBuf.append( c );
1587 while( c != 0 );
1589 OUString aRetStr = aBuf.makeStringAndClear();
1590 return aRetStr;
1593 void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
1594 throw (IllegalArgumentException, RuntimeException, std::exception)
1596 // Init: Remove all locales
1597 sal_Int32 nOldLocaleCount = 0;
1600 Sequence< Locale > aLocaleSeq = getLocales();
1601 nOldLocaleCount = aLocaleSeq.getLength();
1602 if( nOldLocaleCount > 0 )
1604 Locale aLocale = aLocaleSeq[0];
1605 removeLocale( aLocale );
1608 while( nOldLocaleCount > 0 );
1610 // Import data
1611 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1612 BinaryInput aIn( Data, xMCF, m_xContext );
1614 sal_Int32 nVersion = aIn.readInt16();
1615 (void)nVersion;
1616 sal_Int32 nLocaleCount = aIn.readInt16();
1617 sal_Int32 iDefault = aIn.readInt16();
1618 (void)iDefault;
1620 sal_Int32* pPositions = new sal_Int32[nLocaleCount + 1];
1621 for( sal_Int32 i = 0; i < nLocaleCount + 1; i++ )
1622 pPositions[i] = aIn.readInt32();
1624 // Import locales
1625 LocaleItem* pUseAsDefaultItem = NULL;
1626 for( sal_Int32 i = 0; i < nLocaleCount; i++ )
1628 sal_Int32 nPos = pPositions[i];
1629 aIn.seek( nPos );
1631 Locale aLocale;
1632 aLocale.Language = aIn.readString();
1633 aLocale.Country = aIn.readString();
1634 aLocale.Variant = aIn.readString();
1636 sal_Int32 nAfterStringPos = aIn.getPosition();
1637 sal_Int32 nSize = pPositions[i+1] - nAfterStringPos;
1638 Reference< io::XInputStream > xInput = aIn.getInputStreamForSection( nSize );
1639 if( xInput.is() )
1641 LocaleItem* pLocaleItem = new LocaleItem( aLocale );
1642 if( iDefault == i )
1643 pUseAsDefaultItem = pLocaleItem;
1644 m_aLocaleItemVector.push_back( pLocaleItem );
1645 implReadPropertiesFile( pLocaleItem, xInput );
1649 if( pUseAsDefaultItem != NULL )
1650 setDefaultLocale( pUseAsDefaultItem->m_locale );
1652 delete[] pPositions;
1657 // Private helper methods
1659 bool checkNamingSceme( const OUString& aName, const OUString& aNameBase,
1660 Locale& aLocale )
1662 bool bSuccess = false;
1664 sal_Int32 nNameLen = aName.getLength();
1665 sal_Int32 nNameBaseLen = aNameBase.getLength();
1667 // Name has to start with NameBase followed
1668 // by a '_' and at least one more character
1669 if( aName.startsWith( aNameBase ) && nNameBaseLen < nNameLen-1 &&
1670 aName[nNameBaseLen] == '_' )
1672 bSuccess = true;
1674 /* FIXME-BCP47: this uses '_' underscore character as separator and
1675 * also appends Variant, which can't be blindly changed as it would
1676 * violate the naming scheme in use. */
1678 sal_Int32 iStart = nNameBaseLen + 1;
1679 sal_Int32 iNext_ = aName.indexOf( '_', iStart );
1680 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1682 aLocale.Language = aName.copy( iStart, iNext_ - iStart );
1684 iStart = iNext_ + 1;
1685 iNext_ = aName.indexOf( '_', iStart );
1686 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1688 aLocale.Country = aName.copy( iStart, iNext_ - iStart );
1689 aLocale.Variant = aName.copy( iNext_ + 1 );
1691 else
1692 aLocale.Country = aName.copy( iStart );
1694 else
1695 aLocale.Language = aName.copy( iStart );
1697 return bSuccess;
1700 void StringResourcePersistenceImpl::implLoadAllLocales()
1702 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); ++it )
1704 LocaleItem* pLocaleItem = *it;
1705 if( pLocaleItem != NULL )
1706 loadLocale( pLocaleItem );
1710 // Scan locale properties files helper
1711 void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< OUString >& aContentSeq )
1713 Locale aDefaultLocale;
1714 bool bDefaultFound = false;
1716 sal_Int32 nCount = aContentSeq.getLength();
1717 const OUString* pFiles = aContentSeq.getConstArray();
1718 for( int i = 0 ; i < nCount ; i++ )
1720 OUString aCompleteName = pFiles[i];
1721 OUString aPureName;
1722 OUString aExtension;
1723 sal_Int32 iDot = aCompleteName.lastIndexOf( '.' );
1724 sal_Int32 iSlash = aCompleteName.lastIndexOf( '/' );
1725 if( iDot != -1 && iDot > iSlash)
1727 sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0;
1728 aPureName = aCompleteName.copy( iCopyFrom, iDot-iCopyFrom );
1729 aExtension = aCompleteName.copy( iDot + 1 );
1732 if ( aExtension == "properties" )
1734 //OUString aName = aInetObj.getBase();
1735 Locale aLocale;
1737 if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) )
1739 LocaleItem* pLocaleItem = new LocaleItem( aLocale, false );
1740 m_aLocaleItemVector.push_back( pLocaleItem );
1742 if( m_pCurrentLocaleItem == NULL )
1743 m_pCurrentLocaleItem = pLocaleItem;
1745 if( m_pDefaultLocaleItem == NULL )
1747 m_pDefaultLocaleItem = pLocaleItem;
1748 m_bDefaultModified = true;
1752 else if( !bDefaultFound && aExtension == "default" )
1754 //OUString aName = aInetObj.getBase();
1755 Locale aLocale;
1757 if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) )
1758 bDefaultFound = true;
1761 if( bDefaultFound )
1763 LocaleItem* pLocaleItem = getItemForLocale( aDefaultLocale, false );
1764 if( pLocaleItem )
1766 m_pDefaultLocaleItem = pLocaleItem;
1767 m_bDefaultModified = false;
1772 // Scan locale properties files
1773 void StringResourcePersistenceImpl::implScanLocales()
1775 // Dummy implementation, method not called for this
1776 // base class, but pure virtual not possible-
1779 bool StringResourcePersistenceImpl::loadLocale( LocaleItem* pLocaleItem )
1781 bool bSuccess = false;
1783 OSL_ENSURE( pLocaleItem, "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL" );
1784 if( pLocaleItem )
1786 if( pLocaleItem->m_bLoaded )
1788 bSuccess = true;
1790 else
1792 bSuccess = implLoadLocale( pLocaleItem );
1793 pLocaleItem->m_bLoaded = true; // = bSuccess??? -> leads to more tries
1796 return bSuccess;
1799 bool StringResourcePersistenceImpl::implLoadLocale( LocaleItem* )
1801 // Dummy implementation, method not called for this
1802 // base class, but pure virtual not possible-
1803 return false;
1806 OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem )
1808 /* FIXME-BCP47: this uses '_' underscore character as separator and
1809 * also appends Variant, which can't be blindly changed as it would
1810 * violate the naming scheme in use. */
1812 static const char aUnder[] = "_";
1814 OSL_ENSURE( pLocaleItem,
1815 "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL" );
1816 Locale aLocale = pLocaleItem->m_locale;
1818 OUString aRetStr = aUnder;
1819 aRetStr += aLocale.Language;
1821 OUString aCountry = aLocale.Country;
1822 if( !aCountry.isEmpty() )
1824 aRetStr += aUnder;
1825 aRetStr += aCountry;
1828 OUString aVariant = aLocale.Variant;
1829 if( !aVariant.isEmpty() )
1831 aRetStr += aUnder;
1832 aRetStr += aVariant;
1834 return aRetStr;
1837 OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem
1838 ( LocaleItem* pLocaleItem, const OUString& aNameBase )
1840 OUString aFileName = aNameBase;
1841 if( aFileName.isEmpty() )
1842 aFileName = aNameBaseDefaultStr;
1844 aFileName += implGetNameScemeForLocaleItem( pLocaleItem );
1845 return aFileName;
1848 OUString StringResourcePersistenceImpl::implGetPathForLocaleItem
1849 ( LocaleItem* pLocaleItem, const OUString& aNameBase,
1850 const OUString& aLocation, bool bDefaultFile )
1852 OUString aFileName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1853 INetURLObject aInetObj( aLocation );
1854 aInetObj.insertName( aFileName, true, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL );
1855 if( bDefaultFile )
1856 aInetObj.setExtension( OUString( "default" ) );
1857 else
1858 aInetObj.setExtension( OUString( "properties" ) );
1859 OUString aCompleteFileName = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
1860 return aCompleteFileName;
1863 // White space according to Java property files specification in
1864 // http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)
1865 inline bool isWhiteSpace( sal_Unicode c )
1867 bool bWhite = ( c == 0x0020 || // space
1868 c == 0x0009 || // tab
1869 c == 0x000a || // line feed, not always handled by TextInputStream
1870 c == 0x000d || // carriage return, not always handled by TextInputStream
1871 c == 0x000C ); // form feed
1872 return bWhite;
1875 inline void skipWhites( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1877 while( ri < nLen )
1879 if( !isWhiteSpace( pBuf[ri] ) )
1880 break;
1881 ri++;
1885 inline bool isHexDigit( sal_Unicode c, sal_uInt16& nDigitVal )
1887 bool bRet = true;
1888 if( c >= '0' && c <= '9' )
1889 nDigitVal = c - '0';
1890 else if( c >= 'a' && c <= 'f' )
1891 nDigitVal = c - 'a' + 10;
1892 else if( c >= 'A' && c <= 'F' )
1893 nDigitVal = c - 'A' + 10;
1894 else
1895 bRet = false;
1896 return bRet;
1899 sal_Unicode getEscapeChar( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1901 sal_Int32 i = ri;
1903 sal_Unicode cRet = 0;
1904 sal_Unicode c = pBuf[i];
1905 switch( c )
1907 case 't':
1908 cRet = 0x0009;
1909 break;
1910 case 'n':
1911 cRet = 0x000a;
1912 break;
1913 case 'f':
1914 cRet = 0x000c;
1915 break;
1916 case 'r':
1917 cRet = 0x000d;
1918 break;
1919 case '\\':
1920 cRet = '\\';
1921 break;
1922 case 'u':
1924 // Skip multiple u
1925 i++;
1926 while( i < nLen && pBuf[i] == 'u' )
1927 i++;
1929 // Process hex digits
1930 sal_Int32 nDigitCount = 0;
1931 sal_uInt16 nDigitVal;
1932 while( i < nLen && isHexDigit( pBuf[i], nDigitVal ) )
1934 cRet = 16 * cRet + nDigitVal;
1936 nDigitCount++;
1937 if( nDigitCount == 4 )
1939 // Write back position
1940 ri = i;
1941 break;
1943 i++;
1945 break;
1947 default:
1948 cRet = c;
1951 return cRet;
1954 void CheckContinueInNextLine( Reference< io::XTextInputStream2 > xTextInputStream,
1955 OUString& aLine, bool& bEscapePending, const sal_Unicode*& pBuf,
1956 sal_Int32& nLen, sal_Int32& i )
1958 if( i == nLen && bEscapePending )
1960 bEscapePending = false;
1962 if( !xTextInputStream->isEOF() )
1964 aLine = xTextInputStream->readLine();
1965 nLen = aLine.getLength();
1966 pBuf = aLine.getStr();
1967 i = 0;
1969 skipWhites( pBuf, nLen, i );
1974 bool StringResourcePersistenceImpl::implReadPropertiesFile
1975 ( LocaleItem* pLocaleItem, const Reference< io::XInputStream >& xInputStream )
1977 if( !xInputStream.is() || pLocaleItem == NULL )
1978 return false;
1980 bool bSuccess = false;
1981 Reference< io::XTextInputStream2 > xTextInputStream = io::TextInputStream::create( m_xContext );
1983 bSuccess = true;
1985 xTextInputStream->setInputStream( xInputStream );
1987 OUString aEncodingStr = OUString::createFromAscii
1988 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
1989 xTextInputStream->setEncoding( aEncodingStr );
1991 OUString aLine;
1992 while( !xTextInputStream->isEOF() )
1994 aLine = xTextInputStream->readLine();
1996 sal_Int32 nLen = aLine.getLength();
1997 if( 0 == nLen )
1998 continue;
1999 const sal_Unicode* pBuf = aLine.getStr();
2000 OUStringBuffer aBuf;
2001 sal_Unicode c = 0;
2002 sal_Int32 i = 0;
2004 skipWhites( pBuf, nLen, i );
2005 if( i == nLen )
2006 continue; // line contains only white spaces
2008 // Comment?
2009 c = pBuf[i];
2010 if( c == '#' || c == '!' )
2011 continue;
2013 // Scan key
2014 OUString aResourceID;
2015 bool bEscapePending = false;
2016 bool bStrComplete = false;
2017 while( i < nLen && !bStrComplete )
2019 c = pBuf[i];
2020 if( bEscapePending )
2022 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
2023 bEscapePending = false;
2025 else
2027 if( c == '\\' )
2029 bEscapePending = true;
2031 else
2033 if( c == ':' || c == '=' || isWhiteSpace( c ) )
2034 bStrComplete = true;
2035 else
2036 aBuf.append( c );
2039 i++;
2041 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
2042 if( i == nLen )
2043 bStrComplete = true;
2045 if( bStrComplete )
2046 aResourceID = aBuf.makeStringAndClear();
2049 // Ignore lines with empty keys
2050 if( aResourceID.isEmpty() )
2051 continue;
2053 // Scan value
2054 skipWhites( pBuf, nLen, i );
2056 OUString aValueStr;
2057 bEscapePending = false;
2058 bStrComplete = false;
2059 while( i < nLen && !bStrComplete )
2061 c = pBuf[i];
2062 if( c == 0x000a || c == 0x000d ) // line feed/carriage return, not always handled by TextInputStream
2064 i++;
2066 else
2068 if( bEscapePending )
2070 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
2071 bEscapePending = false;
2073 else if( c == '\\' )
2074 bEscapePending = true;
2075 else
2076 aBuf.append( c );
2077 i++;
2079 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
2081 if( i == nLen )
2082 bStrComplete = true;
2084 if( bStrComplete )
2085 aValueStr = aBuf.makeStringAndClear();
2088 // Push into table
2089 pLocaleItem->m_aIdToStringMap[ aResourceID ] = aValueStr;
2090 implScanIdForNumber( aResourceID );
2091 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
2092 rIndexMap[ aResourceID ] = pLocaleItem->m_nNextIndex++;
2095 return bSuccess;
2099 inline sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal )
2101 sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10));
2102 return cRet;
2105 void implWriteCharToBuffer( OUStringBuffer& aBuf, sal_Unicode cu, bool bKey )
2107 if( cu == '\\' )
2109 aBuf.append( '\\' );
2110 aBuf.append( '\\' );
2112 else if( cu == 0x000a )
2114 aBuf.append( '\\' );
2115 aBuf.append( 'n' );
2117 else if( cu == 0x000d )
2119 aBuf.append( '\\' );
2120 aBuf.append( 'r' );
2122 else if( bKey && cu == '=' )
2124 aBuf.append( '\\' );
2125 aBuf.append( '=' );
2127 else if( bKey && cu == ':' )
2129 aBuf.append( '\\' );
2130 aBuf.append( ':' );
2132 // ISO/IEC 8859-1 range according to:
2133 // http://en.wikipedia.org/wiki/ISO/IEC_8859-1
2134 else if( (cu >= 0x20 && cu <= 0x7e) )
2135 //TODO: Check why (cu >= 0xa0 && cu <= 0xFF)
2136 //is encoded in sample properties files
2137 //else if( (cu >= 0x20 && cu <= 0x7e) ||
2138 // (cu >= 0xa0 && cu <= 0xFF) )
2140 aBuf.append( cu );
2142 else
2144 // Unicode encoding
2145 aBuf.append( '\\' );
2146 aBuf.append( 'u' );
2148 sal_uInt16 nVal = cu;
2149 for( sal_uInt16 i = 0 ; i < 4 ; i++ )
2151 sal_uInt16 nDigit = nVal / 0x1000;
2152 nVal -= nDigit * 0x1000;
2153 nVal *= 0x10;
2154 aBuf.append( getHexCharForDigit( nDigit ) );
2159 void implWriteStringWithEncoding( const OUString& aStr,
2160 Reference< io::XTextOutputStream2 > xTextOutputStream, bool bKey )
2162 static sal_Unicode cLineFeed = 0xa;
2164 (void)aStr;
2165 (void)xTextOutputStream;
2167 OUStringBuffer aBuf;
2168 sal_Int32 nLen = aStr.getLength();
2169 const sal_Unicode* pSrc = aStr.getStr();
2170 for( sal_Int32 i = 0 ; i < nLen ; i++ )
2172 sal_Unicode cu = pSrc[i];
2173 implWriteCharToBuffer( aBuf, cu, bKey );
2174 // TODO?: split long lines
2176 if( !bKey )
2177 aBuf.append( cLineFeed );
2179 OUString aWriteStr = aBuf.makeStringAndClear();
2180 xTextOutputStream->writeString( aWriteStr );
2183 bool StringResourcePersistenceImpl::implWritePropertiesFile( LocaleItem* pLocaleItem,
2184 const Reference< io::XOutputStream >& xOutputStream, const OUString& aComment )
2186 static const char aAssignmentStr[] = "=";
2187 static const char aLineFeedStr[] = "\n";
2189 if( !xOutputStream.is() || pLocaleItem == NULL )
2190 return false;
2192 bool bSuccess = false;
2193 Reference< io::XTextOutputStream2 > xTextOutputStream = io::TextOutputStream::create(m_xContext);
2195 xTextOutputStream->setOutputStream( xOutputStream );
2197 OUString aEncodingStr = OUString::createFromAscii
2198 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
2199 xTextOutputStream->setEncoding( aEncodingStr );
2201 xTextOutputStream->writeString( aComment );
2202 xTextOutputStream->writeString( aLineFeedStr );
2204 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
2205 if( !rHashMap.empty() )
2207 // Sort ids according to read order
2208 const IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
2209 IdToIndexMap::const_iterator it_index;
2211 // Find max/min index
2212 sal_Int32 nMinIndex = -1;
2213 sal_Int32 nMaxIndex = -1;
2214 for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); ++it_index )
2216 sal_Int32 nIndex = (*it_index).second;
2217 if( nMinIndex > nIndex || nMinIndex == -1 )
2218 nMinIndex = nIndex;
2219 if( nMaxIndex < nIndex )
2220 nMaxIndex = nIndex;
2222 sal_Int32 nTabSize = nMaxIndex - nMinIndex + 1;
2224 // Create sorted array of pointers to the id strings
2225 const OUString** pIdPtrs = new const OUString*[nTabSize];
2226 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
2227 pIdPtrs[i] = NULL;
2228 for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); ++it_index )
2230 sal_Int32 nIndex = (*it_index).second;
2231 pIdPtrs[nIndex - nMinIndex] = &((*it_index).first);
2234 // Write lines in correct order
2235 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
2237 const OUString* pStr = pIdPtrs[i];
2238 if( pStr != NULL )
2240 OUString aResourceID = *pStr;
2241 IdToStringMap::const_iterator it = rHashMap.find( aResourceID );
2242 if( !( it == rHashMap.end() ) )
2244 implWriteStringWithEncoding( aResourceID, xTextOutputStream, true );
2245 xTextOutputStream->writeString( aAssignmentStr );
2246 OUString aValStr = (*it).second;
2247 implWriteStringWithEncoding( aValStr, xTextOutputStream, false );
2252 delete[] pIdPtrs;
2255 bSuccess = true;
2257 return bSuccess;
2262 // StringResourceWithStorageImpl
2265 // component operations
2266 static Sequence< OUString > getSupportedServiceNames_StringResourceWithStorageImpl()
2268 Sequence< OUString > names(1);
2269 names[0] = "com.sun.star.resource.StringResourceWithStorage";
2270 return names;
2273 static OUString getImplementationName_StringResourceWithStorageImpl()
2275 return OUString( "com.sun.star.comp.scripting.StringResourceWithStorage" );
2278 static Reference< XInterface > SAL_CALL create_StringResourceWithStorageImpl(
2279 Reference< XComponentContext > const & xContext )
2281 return static_cast< ::cppu::OWeakObject * >( new StringResourceWithStorageImpl( xContext ) );
2286 StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext )
2287 : StringResourceWithStorageImpl_BASE( rxContext )
2288 , m_bStorageChanged( false )
2294 StringResourceWithStorageImpl::~StringResourceWithStorageImpl()
2299 // XServiceInfo
2302 OUString StringResourceWithStorageImpl::getImplementationName( ) throw (RuntimeException, std::exception)
2304 return getImplementationName_StringResourceWithStorageImpl();
2307 sal_Bool StringResourceWithStorageImpl::supportsService( const OUString& rServiceName ) throw (RuntimeException, std::exception)
2309 return cppu::supportsService(this, rServiceName);
2312 Sequence< OUString > StringResourceWithStorageImpl::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
2314 return getSupportedServiceNames_StringResourceWithStorageImpl();
2318 // XInitialization
2321 void StringResourceWithStorageImpl::initialize( const Sequence< Any >& aArguments )
2322 throw (Exception, RuntimeException, std::exception)
2324 ::osl::MutexGuard aGuard( getMutex() );
2326 if ( aArguments.getLength() != 5 )
2328 throw RuntimeException(
2329 "StringResourceWithStorageImpl::initialize: invalid number of arguments!" );
2332 bool bOk = (aArguments[0] >>= m_xStorage);
2333 if( bOk && !m_xStorage.is() )
2334 bOk = false;
2336 if( !bOk )
2338 OUString errorMsg("StringResourceWithStorageImpl::initialize: invalid storage");
2339 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2342 implInitializeCommonParameters( aArguments );
2346 // Forwarding calls to base class
2348 // XModifyBroadcaster
2349 void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2350 throw (RuntimeException, std::exception)
2352 StringResourceImpl::addModifyListener( aListener );
2354 void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2355 throw (RuntimeException, std::exception)
2357 StringResourceImpl::removeModifyListener( aListener );
2360 // XStringResourceResolver
2361 OUString StringResourceWithStorageImpl::resolveString( const OUString& ResourceID )
2362 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
2364 return StringResourceImpl::resolveString( ResourceID ) ;
2366 OUString StringResourceWithStorageImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2367 throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
2369 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2371 sal_Bool StringResourceWithStorageImpl::hasEntryForId( const OUString& ResourceID )
2372 throw (RuntimeException, std::exception)
2374 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2376 sal_Bool StringResourceWithStorageImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
2377 const Locale& locale )
2378 throw (RuntimeException, std::exception)
2380 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2382 Sequence< OUString > StringResourceWithStorageImpl::getResourceIDs( )
2383 throw (RuntimeException, std::exception)
2385 return StringResourceImpl::getResourceIDs();
2387 Sequence< OUString > StringResourceWithStorageImpl::getResourceIDsForLocale
2388 ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException, std::exception)
2390 return StringResourceImpl::getResourceIDsForLocale( locale );
2392 Locale StringResourceWithStorageImpl::getCurrentLocale()
2393 throw (RuntimeException, std::exception)
2395 return StringResourceImpl::getCurrentLocale();
2397 Locale StringResourceWithStorageImpl::getDefaultLocale( )
2398 throw (RuntimeException, std::exception)
2400 return StringResourceImpl::getDefaultLocale();
2402 Sequence< Locale > StringResourceWithStorageImpl::getLocales( )
2403 throw (RuntimeException, std::exception)
2405 return StringResourceImpl::getLocales();
2408 // XStringResourceManager
2409 sal_Bool StringResourceWithStorageImpl::isReadOnly()
2410 throw (RuntimeException, std::exception)
2412 return StringResourceImpl::isReadOnly();
2414 void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2415 throw (IllegalArgumentException, RuntimeException, std::exception)
2417 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2419 void StringResourceWithStorageImpl::setDefaultLocale( const Locale& locale )
2420 throw (IllegalArgumentException, RuntimeException,NoSupportException, std::exception)
2422 StringResourceImpl::setDefaultLocale( locale );
2424 void StringResourceWithStorageImpl::setString( const OUString& ResourceID, const OUString& Str )
2425 throw (NoSupportException, RuntimeException, std::exception)
2427 StringResourceImpl::setString( ResourceID, Str );
2429 void StringResourceWithStorageImpl::setStringForLocale
2430 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2431 throw (NoSupportException, RuntimeException, std::exception)
2433 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2435 void StringResourceWithStorageImpl::removeId( const OUString& ResourceID )
2436 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
2438 StringResourceImpl::removeId( ResourceID );
2440 void StringResourceWithStorageImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2441 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
2443 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2445 void StringResourceWithStorageImpl::newLocale( const Locale& locale )
2446 throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
2448 StringResourceImpl::newLocale( locale );
2450 void StringResourceWithStorageImpl::removeLocale( const Locale& locale )
2451 throw (IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
2453 StringResourceImpl::removeLocale( locale );
2455 sal_Int32 StringResourceWithStorageImpl::getUniqueNumericId( )
2456 throw (RuntimeException, NoSupportException, std::exception)
2458 return StringResourceImpl::getUniqueNumericId();
2461 // XStringResourcePersistence
2462 void StringResourceWithStorageImpl::store()
2463 throw (NoSupportException, Exception, RuntimeException, std::exception)
2465 ::osl::MutexGuard aGuard( getMutex() );
2466 implCheckReadOnly( "StringResourceWithStorageImpl::store(): Read only" );
2468 bool bUsedForStore = true;
2469 bool bStoreAll = m_bStorageChanged;
2470 m_bStorageChanged = false;
2471 if( !m_bModified && !bStoreAll )
2472 return;
2474 implStoreAtStorage( m_aNameBase, m_aComment, m_xStorage, bUsedForStore, bStoreAll );
2475 m_bModified = false;
2478 sal_Bool StringResourceWithStorageImpl::isModified( )
2479 throw (RuntimeException, std::exception)
2481 return StringResourcePersistenceImpl::isModified();
2483 void StringResourceWithStorageImpl::setComment( const OUString& Comment )
2484 throw (::com::sun::star::uno::RuntimeException, std::exception)
2486 StringResourcePersistenceImpl::setComment( Comment );
2488 void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage,
2489 const OUString& NameBase, const OUString& Comment )
2490 throw (Exception, RuntimeException, std::exception)
2492 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2494 void StringResourceWithStorageImpl::storeToURL( const OUString& URL,
2495 const OUString& NameBase, const OUString& Comment,
2496 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
2497 throw (Exception, RuntimeException, std::exception)
2499 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2501 Sequence< ::sal_Int8 > StringResourceWithStorageImpl::exportBinary( )
2502 throw (RuntimeException, std::exception)
2504 return StringResourcePersistenceImpl::exportBinary();
2506 void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2507 throw (IllegalArgumentException, RuntimeException, std::exception)
2509 StringResourcePersistenceImpl::importBinary( Data );
2513 // XStringResourceWithStorage
2515 void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage )
2516 throw (Exception, RuntimeException, std::exception)
2518 setStorage( Storage );
2519 store();
2522 void StringResourceWithStorageImpl::setStorage( const Reference< XStorage >& Storage )
2523 throw (IllegalArgumentException, RuntimeException, std::exception)
2525 ::osl::MutexGuard aGuard( getMutex() );
2527 if( !Storage.is() )
2529 OUString errorMsg( "StringResourceWithStorageImpl::setStorage: invalid storage" );
2530 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2533 implLoadAllLocales();
2535 m_xStorage = Storage;
2536 m_bStorageChanged = true;
2541 // Private helper methods
2544 // Scan locale properties files
2545 void StringResourceWithStorageImpl::implScanLocales()
2547 Reference< container::XNameAccess > xNameAccess( m_xStorage, UNO_QUERY );
2548 if( xNameAccess.is() )
2550 Sequence< OUString > aContentSeq = xNameAccess->getElementNames();
2551 implScanLocaleNames( aContentSeq );
2554 implLoadAllLocales();
2557 // Loading
2558 bool StringResourceWithStorageImpl::implLoadLocale( LocaleItem* pLocaleItem )
2560 bool bSuccess = false;
2563 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
2564 aStreamName += ".properties";
2566 Reference< io::XStream > xElementStream =
2567 m_xStorage->openStreamElement( aStreamName, ElementModes::READ );
2569 if( xElementStream.is() )
2571 Reference< io::XInputStream > xInputStream = xElementStream->getInputStream();
2572 if( xInputStream.is() )
2574 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2575 xInputStream->closeInput();
2579 catch( uno::Exception& )
2582 return bSuccess;
2587 // StringResourceWithLocationImpl
2590 // component operations
2591 static Sequence< OUString > getSupportedServiceNames_StringResourceWithLocationImpl()
2593 Sequence< OUString > names(1);
2594 names[0] = "com.sun.star.resource.StringResourceWithLocation";
2595 return names;
2598 static OUString getImplementationName_StringResourceWithLocationImpl()
2600 return OUString( "com.sun.star.comp.scripting.StringResourceWithLocation" );
2603 static Reference< XInterface > SAL_CALL create_StringResourceWithLocationImpl(
2604 Reference< XComponentContext > const & xContext )
2606 return static_cast< ::cppu::OWeakObject * >( new StringResourceWithLocationImpl( xContext ) );
2611 StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext )
2612 : StringResourceWithLocationImpl_BASE( rxContext )
2613 , m_bLocationChanged( false )
2619 StringResourceWithLocationImpl::~StringResourceWithLocationImpl()
2624 // XServiceInfo
2627 OUString StringResourceWithLocationImpl::getImplementationName( ) throw (RuntimeException, std::exception)
2629 return getImplementationName_StringResourceWithLocationImpl();
2632 sal_Bool StringResourceWithLocationImpl::supportsService( const OUString& rServiceName ) throw (RuntimeException, std::exception)
2634 return cppu::supportsService(this, rServiceName);
2637 Sequence< OUString > StringResourceWithLocationImpl::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
2639 return getSupportedServiceNames_StringResourceWithLocationImpl();
2643 // XInitialization
2646 void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArguments )
2647 throw (Exception, RuntimeException, std::exception)
2649 ::osl::MutexGuard aGuard( getMutex() );
2651 if ( aArguments.getLength() != 6 )
2653 throw RuntimeException(
2654 "XInitialization::initialize: invalid number of arguments!" );
2657 bool bOk = (aArguments[0] >>= m_aLocation);
2658 sal_Int32 nLen = m_aLocation.getLength();
2659 if( bOk && nLen == 0 )
2661 bOk = false;
2663 else
2665 if( m_aLocation[nLen - 1] != '/' )
2666 m_aLocation += "/";
2669 if( !bOk )
2671 OUString errorMsg("XInitialization::initialize: invalid URL");
2672 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2676 bOk = (aArguments[5] >>= m_xInteractionHandler);
2677 if( !bOk )
2679 OUString errorMsg("StringResourceWithStorageImpl::initialize: invalid type");
2680 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 5 );
2683 implInitializeCommonParameters( aArguments );
2687 // Forwarding calls to base class
2689 // XModifyBroadcaster
2690 void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2691 throw (RuntimeException, std::exception)
2693 StringResourceImpl::addModifyListener( aListener );
2695 void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2696 throw (RuntimeException, std::exception)
2698 StringResourceImpl::removeModifyListener( aListener );
2701 // XStringResourceResolver
2702 OUString StringResourceWithLocationImpl::resolveString( const OUString& ResourceID )
2703 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
2705 return StringResourceImpl::resolveString( ResourceID ) ;
2707 OUString StringResourceWithLocationImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2708 throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException, std::exception)
2710 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2712 sal_Bool StringResourceWithLocationImpl::hasEntryForId( const OUString& ResourceID )
2713 throw (RuntimeException, std::exception)
2715 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2717 sal_Bool StringResourceWithLocationImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
2718 const Locale& locale )
2719 throw (RuntimeException, std::exception)
2721 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2723 Sequence< OUString > StringResourceWithLocationImpl::getResourceIDs( )
2724 throw (RuntimeException, std::exception)
2726 return StringResourceImpl::getResourceIDs();
2728 Sequence< OUString > StringResourceWithLocationImpl::getResourceIDsForLocale
2729 ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException, std::exception)
2731 return StringResourceImpl::getResourceIDsForLocale( locale );
2733 Locale StringResourceWithLocationImpl::getCurrentLocale()
2734 throw (RuntimeException, std::exception)
2736 return StringResourceImpl::getCurrentLocale();
2738 Locale StringResourceWithLocationImpl::getDefaultLocale( )
2739 throw (RuntimeException, std::exception)
2741 return StringResourceImpl::getDefaultLocale();
2743 Sequence< Locale > StringResourceWithLocationImpl::getLocales( )
2744 throw (RuntimeException, std::exception)
2746 return StringResourceImpl::getLocales();
2749 // XStringResourceManager
2750 sal_Bool StringResourceWithLocationImpl::isReadOnly()
2751 throw (RuntimeException, std::exception)
2753 return StringResourceImpl::isReadOnly();
2755 void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2756 throw (IllegalArgumentException, RuntimeException, std::exception)
2758 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2760 void StringResourceWithLocationImpl::setDefaultLocale( const Locale& locale )
2761 throw (IllegalArgumentException, RuntimeException,NoSupportException, std::exception)
2763 StringResourceImpl::setDefaultLocale( locale );
2765 void StringResourceWithLocationImpl::setString( const OUString& ResourceID, const OUString& Str )
2766 throw (NoSupportException, RuntimeException, std::exception)
2768 StringResourceImpl::setString( ResourceID, Str );
2770 void StringResourceWithLocationImpl::setStringForLocale
2771 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2772 throw (NoSupportException, RuntimeException, std::exception)
2774 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2776 void StringResourceWithLocationImpl::removeId( const OUString& ResourceID )
2777 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
2779 StringResourceImpl::removeId( ResourceID );
2781 void StringResourceWithLocationImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2782 throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException, std::exception)
2784 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2786 void StringResourceWithLocationImpl::newLocale( const Locale& locale )
2787 throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
2789 StringResourceImpl::newLocale( locale );
2791 void StringResourceWithLocationImpl::removeLocale( const Locale& locale )
2792 throw (IllegalArgumentException, RuntimeException, NoSupportException, std::exception)
2794 StringResourceImpl::removeLocale( locale );
2796 sal_Int32 StringResourceWithLocationImpl::getUniqueNumericId( )
2797 throw (RuntimeException, NoSupportException, std::exception)
2799 return StringResourceImpl::getUniqueNumericId();
2802 // XStringResourcePersistence
2803 void StringResourceWithLocationImpl::store()
2804 throw (NoSupportException, Exception, RuntimeException, std::exception)
2806 ::osl::MutexGuard aGuard( getMutex() );
2807 implCheckReadOnly( "StringResourceWithLocationImpl::store(): Read only" );
2809 bool bUsedForStore = true;
2810 bool bStoreAll = m_bLocationChanged;
2811 m_bLocationChanged = false;
2812 if( !m_bModified && !bStoreAll )
2813 return;
2815 Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2816 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2817 xFileAccess, bUsedForStore, bStoreAll );
2818 m_bModified = false;
2821 sal_Bool StringResourceWithLocationImpl::isModified( )
2822 throw (RuntimeException, std::exception)
2824 return StringResourcePersistenceImpl::isModified();
2826 void StringResourceWithLocationImpl::setComment( const OUString& Comment )
2827 throw (::com::sun::star::uno::RuntimeException, std::exception)
2829 StringResourcePersistenceImpl::setComment( Comment );
2831 void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage,
2832 const OUString& NameBase, const OUString& Comment )
2833 throw (Exception, RuntimeException, std::exception)
2835 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2837 void StringResourceWithLocationImpl::storeToURL( const OUString& URL,
2838 const OUString& NameBase, const OUString& Comment,
2839 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
2840 throw (Exception, RuntimeException, std::exception)
2842 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2844 Sequence< ::sal_Int8 > StringResourceWithLocationImpl::exportBinary( )
2845 throw (RuntimeException, std::exception)
2847 return StringResourcePersistenceImpl::exportBinary();
2849 void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2850 throw (IllegalArgumentException, RuntimeException, std::exception)
2852 StringResourcePersistenceImpl::importBinary( Data );
2856 // XStringResourceWithLocation
2858 // XStringResourceWithLocation
2859 void StringResourceWithLocationImpl::storeAsURL( const OUString& URL )
2860 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
2862 setURL( URL );
2863 store();
2866 void StringResourceWithLocationImpl::setURL( const OUString& URL )
2867 throw (css::lang::IllegalArgumentException,
2868 css::lang::NoSupportException,
2869 css::uno::RuntimeException, std::exception)
2871 ::osl::MutexGuard aGuard( getMutex() );
2872 implCheckReadOnly( "StringResourceWithLocationImpl::setURL(): Read only" );
2874 sal_Int32 nLen = URL.getLength();
2875 if( nLen == 0 )
2877 OUString errorMsg( "StringResourceWithLocationImpl::setURL: invalid URL" );
2878 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2881 implLoadAllLocales();
2883 // Delete files at old location
2884 bool bUsedForStore = false;
2885 bool bStoreAll = false;
2886 bool bKillAll = true;
2887 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2888 getFileAccess(), bUsedForStore, bStoreAll, bKillAll );
2890 m_aLocation = URL;
2891 m_bLocationChanged = true;
2896 // Private helper methods
2899 // Scan locale properties files
2900 void StringResourceWithLocationImpl::implScanLocales()
2902 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2903 if( xFileAccess.is() && xFileAccess->isFolder( m_aLocation ) )
2905 Sequence< OUString > aContentSeq = xFileAccess->getFolderContents( m_aLocation, false );
2906 implScanLocaleNames( aContentSeq );
2910 // Loading
2911 bool StringResourceWithLocationImpl::implLoadLocale( LocaleItem* pLocaleItem )
2913 bool bSuccess = false;
2915 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2916 if( xFileAccess.is() )
2918 OUString aCompleteFileName =
2919 implGetPathForLocaleItem( pLocaleItem, m_aNameBase, m_aLocation );
2921 Reference< io::XInputStream > xInputStream;
2924 xInputStream = xFileAccess->openFileRead( aCompleteFileName );
2926 catch( Exception& )
2928 if( xInputStream.is() )
2930 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2931 xInputStream->closeInput();
2935 return bSuccess;
2938 const Reference< ucb::XSimpleFileAccess3 > StringResourceWithLocationImpl::getFileAccess()
2940 ::osl::MutexGuard aGuard( getMutex() );
2942 if( !m_xSFI.is() )
2944 m_xSFI = ucb::SimpleFileAccess::create(m_xContext);
2946 if( m_xSFI.is() && m_xInteractionHandler.is() )
2947 m_xSFI->setInteractionHandler( m_xInteractionHandler );
2949 return m_xSFI;
2954 // component export operations
2957 static const struct ::cppu::ImplementationEntry s_component_entries [] =
2960 create_StringResourceImpl, getImplementationName_StringResourceImpl,
2961 getSupportedServiceNames_StringResourceImpl,
2962 ::cppu::createSingleComponentFactory,
2963 0, 0
2966 create_StringResourceWithLocationImpl, getImplementationName_StringResourceWithLocationImpl,
2967 getSupportedServiceNames_StringResourceWithLocationImpl,
2968 ::cppu::createSingleComponentFactory,
2969 0, 0
2972 create_StringResourceWithStorageImpl, getImplementationName_StringResourceWithStorageImpl,
2973 getSupportedServiceNames_StringResourceWithStorageImpl,
2974 ::cppu::createSingleComponentFactory,
2975 0, 0
2977 { 0, 0, 0, 0, 0, 0 }
2982 } // namespace dlgprov
2987 // component exports
2990 extern "C"
2992 SAL_DLLPUBLIC_EXPORT void * SAL_CALL stringresource_component_getFactory(
2993 const sal_Char * pImplName, void * pServiceManager,
2994 void * pRegistryKey )
2996 return ::cppu::component_getFactoryHelper(
2997 pImplName, pServiceManager, pRegistryKey, ::stringresource::s_component_entries );
3001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */