LibreOffice Module scripting (master) 1
stringresource.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
21#include "stringresource.hxx"
22#include <com/sun/star/io/TempFile.hpp>
23#include <com/sun/star/io/TextInputStream.hpp>
24#include <com/sun/star/io/TextOutputStream.hpp>
25#include <com/sun/star/io/XStream.hpp>
26#include <com/sun/star/io/XSeekable.hpp>
27#include <com/sun/star/embed/ElementModes.hpp>
28#include <com/sun/star/lang/NoSupportException.hpp>
29#include <com/sun/star/resource/MissingResourceException.hpp>
31#include <com/sun/star/beans/XPropertySet.hpp>
32#include <com/sun/star/container/ElementExistException.hpp>
33#include <com/sun/star/ucb/SimpleFileAccess.hpp>
34
35#include <osl/diagnose.h>
36#include <o3tl/string_view.hxx>
37#include <rtl/ref.hxx>
38#include <rtl/tencinfo.h>
39#include <rtl/ustrbuf.hxx>
40#include <tools/urlobj.hxx>
41#include <unotools/tempfile.hxx>
43#include <sal/log.hxx>
44
45using namespace ::com::sun::star;
46using namespace ::com::sun::star::lang;
47using namespace ::com::sun::star::uno;
48using namespace ::com::sun::star::ucb;
49using namespace ::com::sun::star::util;
50using namespace ::com::sun::star::embed;
51using namespace ::com::sun::star::container;
52
53
55{
56
57// StringResourceImpl
58
59extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
61 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
62{
63 return cppu::acquire(new StringResourcePersistenceImpl(context));
64}
65
66
67StringResourceImpl::StringResourceImpl( const Reference< XComponentContext >& rxContext )
68 : m_xContext( rxContext )
69 , m_pCurrentLocaleItem( nullptr )
70 , m_pDefaultLocaleItem( nullptr )
71 , m_bDefaultModified( false )
72 , m_bModified( false )
73 , m_bReadOnly( false )
74 , m_nNextUniqueNumericId( UNIQUE_NUMBER_NEEDS_INITIALISATION )
75{
76}
77
78
80{
81}
82
83
84// XServiceInfo
85
87{
88 return "com.sun.star.comp.scripting.StringResource";
89}
90
91sal_Bool StringResourceImpl::supportsService( const OUString& rServiceName )
92{
93 return cppu::supportsService(this, rServiceName);
94}
95
97{
98 return { "com.sun.star.resource.StringResource" };
99}
100
101
102// XModifyBroadcaster
103
104void StringResourceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
105{
106 if( !aListener.is() )
107 throw RuntimeException();
108
109 std::unique_lock aGuard( m_aMutex );
110 m_aListenerContainer.addInterface( aGuard, aListener );
111}
112
113void StringResourceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
114{
115 if( !aListener.is() )
116 throw RuntimeException();
117
118 std::unique_lock aGuard( m_aMutex );
119 m_aListenerContainer.removeInterface( aGuard, aListener );
120}
121
122
123// XStringResourceResolver
124
126 ( const OUString& ResourceID, LocaleItem* pLocaleItem )
127{
128 OUString aRetStr;
129 bool bSuccess = false;
130 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
131 {
132 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
133 if( it != pLocaleItem->m_aIdToStringMap.end() )
134 {
135 aRetStr = (*it).second;
136 bSuccess = true;
137 }
138 }
139 if( !bSuccess )
140 {
141 throw css::resource::MissingResourceException( "StringResourceImpl: No entry for ResourceID: " + ResourceID );
142 }
143 return aRetStr;
144}
145
146OUString StringResourceImpl::resolveString( const OUString& ResourceID )
147{
148 std::unique_lock aGuard( m_aMutex );
149 return implResolveString( ResourceID, m_pCurrentLocaleItem );
150}
151
152OUString StringResourceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
153{
154 std::unique_lock aGuard( m_aMutex );
155 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
156 return implResolveString( ResourceID, pLocaleItem );
157}
158
159bool StringResourceImpl::implHasEntryForId( const OUString& ResourceID, LocaleItem* pLocaleItem )
160{
161 bool bSuccess = false;
162 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
163 {
164 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
165 if( it != pLocaleItem->m_aIdToStringMap.end() )
166 bSuccess = true;
167 }
168 return bSuccess;
169}
170
171sal_Bool StringResourceImpl::hasEntryForId( const OUString& ResourceID )
172{
173 std::unique_lock aGuard( m_aMutex );
174 return implHasEntryForId( ResourceID, m_pCurrentLocaleItem );
175}
176
178 const Locale& locale )
179{
180 std::unique_lock aGuard( m_aMutex );
181 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
182 return implHasEntryForId( ResourceID, pLocaleItem );
183}
184
186{
187 Sequence< OUString > aIDSeq( 0 );
188 if( pLocaleItem && loadLocale( pLocaleItem ) )
189 {
190 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
191 sal_Int32 nResourceIDCount = rHashMap.size();
192 aIDSeq.realloc( nResourceIDCount );
193 OUString* pStrings = aIDSeq.getArray();
194
195 int iTarget = 0;
196 for( const auto& rEntry : rHashMap )
197 {
198 OUString aStr = rEntry.first;
199 pStrings[iTarget] = aStr;
200 iTarget++;
201 }
202 }
203 return aIDSeq;
204}
205
207 ( const Locale& locale )
208{
209 std::unique_lock aGuard( m_aMutex );
210 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
211 return implGetResourceIDs( pLocaleItem );
212}
213
215{
216 std::unique_lock aGuard( m_aMutex );
218}
219
221{
222 std::unique_lock aGuard( m_aMutex );
223
224 Locale aRetLocale;
225 if( m_pCurrentLocaleItem != nullptr )
226 aRetLocale = m_pCurrentLocaleItem->m_locale;
227 return aRetLocale;
228}
229
231{
232 std::unique_lock aGuard( m_aMutex );
233
234 Locale aRetLocale;
235 if( m_pDefaultLocaleItem != nullptr )
236 aRetLocale = m_pDefaultLocaleItem->m_locale;
237 return aRetLocale;
238}
239
241{
242 std::unique_lock aGuard( m_aMutex );
243
244 sal_Int32 nSize = m_aLocaleItemVector.size();
245 Sequence< Locale > aLocalSeq( nSize );
246 Locale* pLocales = aLocalSeq.getArray();
247 int iTarget = 0;
248 for( const auto& pLocaleItem : m_aLocaleItemVector )
249 {
250 pLocales[iTarget] = pLocaleItem->m_locale;
251 iTarget++;
252 }
253 return aLocalSeq;
254}
255
256
257// XStringResourceManager
258
259void StringResourceImpl::implCheckReadOnly( const char* pExceptionMsg )
260{
261 if( m_bReadOnly )
262 {
263 OUString errorMsg = OUString::createFromAscii( pExceptionMsg );
264 throw NoSupportException( errorMsg );
265 }
266}
267
269{
270 return m_bReadOnly;
271}
272
273void StringResourceImpl::implSetCurrentLocale( std::unique_lock<std::mutex>& rGuard, const Locale& locale,
274 bool FindClosestMatch, bool bUseDefaultIfNoMatch )
275{
276 LocaleItem* pLocaleItem = nullptr;
277 if( FindClosestMatch )
278 pLocaleItem = getClosestMatchItemForLocale( locale );
279 else
280 pLocaleItem = getItemForLocale( locale, true );
281
282 if( pLocaleItem == nullptr && bUseDefaultIfNoMatch )
283 pLocaleItem = m_pDefaultLocaleItem;
284
285 if( pLocaleItem != nullptr )
286 {
287 (void)loadLocale( pLocaleItem );
288 m_pCurrentLocaleItem = pLocaleItem;
289
290 // Only notify without modifying
291 implNotifyListeners(rGuard);
292 }
293}
294
295void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
296{
297 std::unique_lock aGuard( m_aMutex );
298 implSetCurrentLocale( aGuard, locale, FindClosestMatch, false/*bUseDefaultIfNoMatch*/ );
299}
300
301void StringResourceImpl::setDefaultLocale( const Locale& locale )
302{
303 std::unique_lock aGuard( m_aMutex );
304 implCheckReadOnly( "StringResourceImpl::setDefaultLocale(): Read only" );
305
306 LocaleItem* pLocaleItem = getItemForLocale( locale, true );
307 if( pLocaleItem && pLocaleItem != m_pDefaultLocaleItem )
308 {
310 {
312 std::make_unique<LocaleItem>( m_pDefaultLocaleItem->m_locale ) );
313 }
314
315 m_pDefaultLocaleItem = pLocaleItem;
316 m_bDefaultModified = true;
317 implModified(aGuard);
318 }
319}
320
321void StringResourceImpl::implSetString( std::unique_lock<std::mutex>& rGuard, const OUString& ResourceID,
322 const OUString& Str, LocaleItem* pLocaleItem )
323{
324 if( !(pLocaleItem != nullptr && loadLocale( pLocaleItem )) )
325 return;
326
327 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
328
329 IdToStringMap::iterator it = rHashMap.find( ResourceID );
330 bool bNew = ( it == rHashMap.end() );
331 if( bNew )
332 {
333 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
334 rIndexMap[ ResourceID ] = pLocaleItem->m_nNextIndex++;
335 implScanIdForNumber( ResourceID );
336 }
337 rHashMap[ ResourceID ] = Str;
338 pLocaleItem->m_bModified = true;
339 implModified(rGuard);
340}
341
342void StringResourceImpl::setString( const OUString& ResourceID, const OUString& Str )
343{
344 std::unique_lock aGuard( m_aMutex );
345 implCheckReadOnly( "StringResourceImpl::setString(): Read only" );
346 implSetString( aGuard, ResourceID, Str, m_pCurrentLocaleItem );
347}
348
350 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
351{
352 std::unique_lock aGuard( m_aMutex );
353 implCheckReadOnly( "StringResourceImpl::setStringForLocale(): Read only" );
354 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
355 implSetString( aGuard, ResourceID, Str, pLocaleItem );
356}
357
358void StringResourceImpl::implRemoveId( std::unique_lock<std::mutex>& rGuard, const OUString& ResourceID, LocaleItem* pLocaleItem )
359{
360 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
361 {
362 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
363 IdToStringMap::iterator it = rHashMap.find( ResourceID );
364 if( it == rHashMap.end() )
365 {
366 throw css::resource::MissingResourceException( "StringResourceImpl: No entries for ResourceID: " + ResourceID );
367 }
368 rHashMap.erase( it );
369 pLocaleItem->m_bModified = true;
370 implModified(rGuard);
371 }
372}
373
374void StringResourceImpl::removeId( const OUString& ResourceID )
375{
376 std::unique_lock aGuard( m_aMutex );
377 implCheckReadOnly( "StringResourceImpl::removeId(): Read only" );
378 implRemoveId( aGuard, ResourceID, m_pCurrentLocaleItem );
379}
380
381void StringResourceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
382{
383 std::unique_lock aGuard( m_aMutex );
384 implCheckReadOnly( "StringResourceImpl::removeIdForLocale(): Read only" );
385 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
386 implRemoveId( aGuard, ResourceID, pLocaleItem );
387}
388
389void StringResourceImpl::newLocale( const Locale& locale )
390{
391 std::unique_lock aGuard( m_aMutex );
392 implCheckReadOnly( "StringResourceImpl::newLocale(): Read only" );
393
394 if( getItemForLocale( locale, false ) != nullptr )
395 {
396 throw ElementExistException( "StringResourceImpl: locale already exists" );
397 }
398
399 // TODO?: Check if locale is valid? How?
400 //if (!bValid)
401 //{
402 // OUString errorMsg("StringResourceImpl: Invalid locale");
403 // throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
404 //}
405
406 LocaleItem* pLocaleItem = new LocaleItem( locale );
407 m_aLocaleItemVector.emplace_back( pLocaleItem );
408 pLocaleItem->m_bModified = true;
409
410 // Copy strings from default locale
411 LocaleItem* pCopyFromItem = m_pDefaultLocaleItem;
412 if( pCopyFromItem == nullptr )
413 pCopyFromItem = m_pCurrentLocaleItem;
414 if( pCopyFromItem != nullptr && loadLocale( pCopyFromItem ) )
415 {
416 const IdToStringMap& rSourceMap = pCopyFromItem->m_aIdToStringMap;
417 IdToStringMap& rTargetMap = pLocaleItem->m_aIdToStringMap;
418 for( const auto& rEntry : rSourceMap )
419 {
420 OUString aId = rEntry.first;
421 OUString aStr = rEntry.second;
422 rTargetMap[ aId ] = aStr;
423 }
424
425 const IdToIndexMap& rSourceIndexMap = pCopyFromItem->m_aIdToIndexMap;
426 IdToIndexMap& rTargetIndexMap = pLocaleItem->m_aIdToIndexMap;
427 for( const auto& rIndex : rSourceIndexMap )
428 {
429 OUString aId = rIndex.first;
430 sal_Int32 nIndex = rIndex.second;
431 rTargetIndexMap[ aId ] = nIndex;
432 }
433 pLocaleItem->m_nNextIndex = pCopyFromItem->m_nNextIndex;
434 }
435
436 if( m_pCurrentLocaleItem == nullptr )
437 m_pCurrentLocaleItem = pLocaleItem;
438
439 if( m_pDefaultLocaleItem == nullptr )
440 {
441 m_pDefaultLocaleItem = pLocaleItem;
442 m_bDefaultModified = true;
443 }
444
445 implModified(aGuard);
446}
447
448void StringResourceImpl::removeLocale( const Locale& locale )
449{
450 std::unique_lock aGuard( m_aMutex );
451 implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" );
452
453 LocaleItem* pRemoveItem = getItemForLocale( locale, true );
454 if( !pRemoveItem )
455 return;
456
457 // Last locale?
458 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
459 if( nLocaleCount > 1 )
460 {
461 if( m_pCurrentLocaleItem == pRemoveItem ||
462 m_pDefaultLocaleItem == pRemoveItem )
463 {
464 LocaleItem* pFallbackItem = nullptr;
465 for( const auto& pLocaleItem : m_aLocaleItemVector )
466 {
467 if( pLocaleItem.get() != pRemoveItem )
468 {
469 pFallbackItem = pLocaleItem.get();
470 break;
471 }
472 }
473 if( m_pCurrentLocaleItem == pRemoveItem )
474 {
475 setCurrentLocale( pFallbackItem->m_locale, false/*FindClosestMatch*/ );
476 }
477 if( m_pDefaultLocaleItem == pRemoveItem )
478 {
479 setDefaultLocale( pFallbackItem->m_locale );
480 }
481 }
482 }
483 auto it = std::find_if(m_aLocaleItemVector.begin(), m_aLocaleItemVector.end(),
484 [&pRemoveItem](const std::unique_ptr<LocaleItem>& rxItem) { return rxItem.get() == pRemoveItem; });
485 if (it == m_aLocaleItemVector.end())
486 return;
487
488 // Remember locale item to delete file while storing
489 m_aDeletedLocaleItemVector.push_back( std::move(*it) );
490
491 // Last locale?
492 if( nLocaleCount == 1 )
493 {
496 {
498 std::make_unique<LocaleItem>( m_pDefaultLocaleItem->m_locale ) );
499 }
500 m_pCurrentLocaleItem = nullptr;
501 m_pDefaultLocaleItem = nullptr;
502 }
503
504 m_aLocaleItemVector.erase( it );
505
506 implModified(aGuard);
507}
508
509void StringResourceImpl::implScanIdForNumber( const OUString& ResourceID )
510{
511 const sal_Unicode* pSrc = ResourceID.getStr();
512 sal_Int32 nLen = ResourceID.getLength();
513
514 sal_Int32 nNumber = 0;
515 for( sal_Int32 i = 0 ; i < nLen ; i++ )
516 {
517 sal_Unicode c = pSrc[i];
518 if( c >= '0' && c <= '9' )
519 {
520 sal_uInt16 nDigitVal = c - '0';
521 nNumber = 10*nNumber + nDigitVal;
522 }
523 else
524 break;
525 }
526
527 if( m_nNextUniqueNumericId < nNumber + 1 )
528 m_nNextUniqueNumericId = nNumber + 1;
529}
530
532{
534 {
537 }
538
540 {
541 throw NoSupportException( "getUniqueNumericId: Extended sal_Int32 range" );
542 }
544}
545
546
547// Private helper methods
548
550 ( const Locale& locale, bool bException )
551{
552 LocaleItem* pRetItem = nullptr;
553
554 // Search for locale
555 for( auto& pLocaleItem : m_aLocaleItemVector )
556 {
557 if( pLocaleItem )
558 {
559 Locale& cmp_locale = pLocaleItem->m_locale;
560 if( cmp_locale.Language == locale.Language &&
561 cmp_locale.Country == locale.Country &&
562 cmp_locale.Variant == locale.Variant )
563 {
564 pRetItem = pLocaleItem.get();
565 break;
566 }
567 }
568 }
569
570 if( pRetItem == nullptr && bException )
571 {
572 throw IllegalArgumentException( "StringResourceImpl: Invalid locale", Reference< XInterface >(), 0 );
573 }
574 return pRetItem;
575}
576
577// Returns the LocaleItem for a given locale, if it exists, otherwise NULL.
578// This method performs a closest match search, at least the language must match.
580{
581 LocaleItem* pRetItem = nullptr;
582
583 ::std::vector< Locale > aLocales( m_aLocaleItemVector.size());
584 size_t i = 0;
585 for( const auto& pLocaleItem : m_aLocaleItemVector )
586 {
587 aLocales[i] = (pLocaleItem ? pLocaleItem->m_locale : Locale());
588 ++i;
589 }
590 ::std::vector< Locale >::const_iterator iFound( LanguageTag::getMatchingFallback( aLocales, locale));
591 if (iFound != aLocales.end())
592 pRetItem = (m_aLocaleItemVector.begin() + (iFound - aLocales.begin()))->get();
593
594 return pRetItem;
595}
596
597void StringResourceImpl::implModified(std::unique_lock<std::mutex>& rGuard)
598{
599 m_bModified = true;
600 implNotifyListeners(rGuard);
601}
602
603void StringResourceImpl::implNotifyListeners(std::unique_lock<std::mutex>& rGuard)
604{
605 EventObject aEvent;
606 aEvent.Source = getXWeak();
608 [&aEvent](const css::uno::Reference<XModifyListener>& xListener)
609 {
610 xListener->modified(aEvent);
611 }
612 );
613}
614
615
616// Loading
617
619{
620 // Base implementation has nothing to load
621 return true;
622}
623
625{
626 // Base implementation has nothing to load
627}
628
629
630// StringResourcePersistenceImpl
631
632
633StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext )
635{
636}
637
638
640{
641}
642
643
644// XServiceInfo
645
646
648{
649 return "com.sun.star.comp.scripting.StringResource";
650}
651
652
654{
655 return cppu::supportsService( this, rServiceName );
656}
657
658
660{
662}
663
664
665// XInitialization base functionality for derived classes
666
667
668constexpr OUStringLiteral aNameBaseDefaultStr = u"strings";
669
671 ( std::unique_lock<std::mutex>& rGuard, const Sequence< Any >& aArguments )
672{
673 bool bReadOnlyOk = (aArguments[1] >>= m_bReadOnly);
674 if( !bReadOnlyOk )
675 {
676 throw IllegalArgumentException( "XInitialization::initialize: Expected ReadOnly flag", Reference< XInterface >(), 1 );
677 }
678
679 css::lang::Locale aCurrentLocale;
680 bool bLocaleOk = (aArguments[2] >>= aCurrentLocale);
681 if( !bLocaleOk )
682 {
683 throw IllegalArgumentException( "XInitialization::initialize: Expected Locale", Reference< XInterface >(), 2 );
684 }
685
686 bool bNameBaseOk = (aArguments[3] >>= m_aNameBase);
687 if( !bNameBaseOk )
688 {
689 throw IllegalArgumentException( "XInitialization::initialize: Expected NameBase string", Reference< XInterface >(), 3 );
690 }
691 if( m_aNameBase.isEmpty() )
693
694 bool bCommentOk = (aArguments[4] >>= m_aComment);
695 if( !bCommentOk )
696 {
697 throw IllegalArgumentException( "XInitialization::initialize: Expected Comment string", Reference< XInterface >(), 4 );
698 }
699
701
702 implSetCurrentLocale( rGuard, aCurrentLocale, true/*FindClosestMatch*/, true/*bUseDefaultIfNoMatch*/ );
703}
704
705
706// Forwarding calls to base class
707
708// XModifyBroadcaster
709void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
710{
712}
713void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
714{
716}
717
718// XStringResourceResolver
719OUString StringResourcePersistenceImpl::resolveString( const OUString& ResourceID )
720{
721 return StringResourceImpl::resolveString( ResourceID ) ;
722}
723OUString StringResourcePersistenceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
724{
725 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
726}
728{
729 return StringResourceImpl::hasEntryForId( ResourceID ) ;
730}
732 const Locale& locale )
733{
734 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
735}
737{
739}
741{
743}
745{
747}
748
749// XStringResourceManager
751{
753}
754void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
755{
756 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
757}
759{
761}
763{
765}
766void StringResourcePersistenceImpl::setString( const OUString& ResourceID, const OUString& Str )
767{
768 StringResourceImpl::setString( ResourceID, Str );
769}
771 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
772{
773 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
774}
776 ( const Locale& locale )
777{
779}
780void StringResourcePersistenceImpl::removeId( const OUString& ResourceID )
781{
782 StringResourceImpl::removeId( ResourceID );
783}
784void StringResourcePersistenceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
785{
786 StringResourceImpl::removeIdForLocale( ResourceID, locale );
787}
789{
791}
793{
795}
797{
799}
800
801
802// XStringResourcePersistence
803
805{
806}
807
809{
810 std::unique_lock aGuard( m_aMutex );
811
812 return m_bModified;
813}
814
815void StringResourcePersistenceImpl::setComment( const OUString& Comment )
816{
818}
819
820void StringResourcePersistenceImpl::storeToStorage( const Reference< XStorage >& Storage,
821 const OUString& NameBase, const OUString& Comment )
822{
823 std::unique_lock aGuard( m_aMutex );
824
825 implStoreAtStorage( NameBase, Comment, Storage, false/*bUsedForStore*/, true/*bStoreAll*/ );
826}
827
829(
830 const OUString& aNameBase,
831 const OUString& aComment,
832 const Reference< css::embed::XStorage >& Storage,
833 bool bUsedForStore,
834 bool bStoreAll
835)
836{
837 // Delete files for deleted locales
838 if( bUsedForStore )
839 {
840 for( auto& pLocaleItem : m_aDeletedLocaleItemVector )
841 {
842 if( pLocaleItem )
843 {
844 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), m_aNameBase ) + ".properties";
845
846 try
847 {
848 Storage->removeElement( aStreamName );
849 }
850 catch( Exception& )
851 {}
852
853 pLocaleItem.reset();
854 }
855 }
856 m_aDeletedLocaleItemVector.clear();
857 }
858
859 for( auto& pLocaleItem : m_aLocaleItemVector )
860 {
861 if( pLocaleItem != nullptr && (bStoreAll || pLocaleItem->m_bModified) &&
862 loadLocale( pLocaleItem.get() ) )
863 {
864 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), aNameBase ) + ".properties";
865
866 Reference< io::XStream > xElementStream =
867 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
868
869 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
870 OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!" );
871 if ( xProps.is() )
872 {
873 OUString aPropName("MediaType");
874 xProps->setPropertyValue( aPropName, uno::Any( OUString("text/plain") ) );
875
876 aPropName = "UseCommonStoragePasswordEncryption";
877 xProps->setPropertyValue( aPropName, uno::Any( true ) );
878 }
879
880 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
881 if( xOutputStream.is() )
882 implWritePropertiesFile( pLocaleItem.get(), xOutputStream, aComment );
883 xOutputStream->closeOutput();
884
885 if( bUsedForStore )
886 pLocaleItem->m_bModified = false;
887 }
888 }
889
890 // Delete files for changed defaults
891 if( bUsedForStore )
892 {
893 for( auto& pLocaleItem : m_aChangedDefaultLocaleVector )
894 {
895 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), m_aNameBase ) + ".default";
896
897 try
898 {
899 Storage->removeElement( aStreamName );
900 }
901 catch( Exception& )
902 {}
903
904 pLocaleItem.reset();
905 }
906 m_aChangedDefaultLocaleVector.clear();
907 }
908
909 // Default locale
910 if( !(m_pDefaultLocaleItem != nullptr && (bStoreAll || m_bDefaultModified)) )
911 return;
912
913 OUString aStreamName = implGetFileNameForLocaleItem( m_pDefaultLocaleItem, aNameBase ) + ".default";
914
915 Reference< io::XStream > xElementStream =
916 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
917
918 // Only create stream without content
919 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
920 xOutputStream->closeOutput();
921
922 if( bUsedForStore )
923 m_bDefaultModified = false;
924}
925
927 const OUString& NameBase, const OUString& Comment,
928 const Reference< css::task::XInteractionHandler >& Handler )
929{
930 std::unique_lock aGuard( m_aMutex );
931
932 Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create(m_xContext);
933 if( xFileAccess.is() && Handler.is() )
934 xFileAccess->setInteractionHandler( Handler );
935
936 implStoreAtLocation( URL, NameBase, Comment, xFileAccess, false/*bUsedForStore*/, true/*bStoreAll*/ );
937}
938
940(
941 std::u16string_view Location,
942 const OUString& aNameBase,
943 const css::uno::Reference< css::ucb::XSimpleFileAccess3 >& xFileAccess
944)
945{
946 // Delete files for deleted locales
947 for( auto& pLocaleItem : m_aDeletedLocaleItemVector )
948 {
949 if( pLocaleItem )
950 {
951 OUString aCompleteFileName =
952 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location );
953 if( xFileAccess->exists( aCompleteFileName ) )
954 xFileAccess->kill( aCompleteFileName );
955
956 pLocaleItem.reset();
957 }
958 }
959 m_aDeletedLocaleItemVector.clear();
960}
961
963(
964 std::u16string_view Location,
965 const OUString& aNameBase,
966 const css::uno::Reference< css::ucb::XSimpleFileAccess3 >& xFileAccess
967)
968{
969 // Delete files for changed defaults
970 for( auto& pLocaleItem : m_aChangedDefaultLocaleVector )
971 {
972 OUString aCompleteFileName =
973 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location, true );
974 if( xFileAccess->exists( aCompleteFileName ) )
975 xFileAccess->kill( aCompleteFileName );
976 pLocaleItem.reset();
977 }
978 m_aChangedDefaultLocaleVector.clear();
979}
980
982(
983 std::u16string_view Location,
984 const OUString& aNameBase,
985 const OUString& aComment,
986 const Reference< ucb::XSimpleFileAccess3 >& xFileAccess,
987 bool bUsedForStore,
988 bool bStoreAll,
989 bool bKillAll
990)
991{
992 // Delete files for deleted locales
993 if( bUsedForStore || bKillAll )
994 implKillRemovedLocaleFiles( Location, aNameBase, xFileAccess );
995
996 for( auto& pLocaleItem : m_aLocaleItemVector )
997 {
998 if( pLocaleItem != nullptr && (bStoreAll || bKillAll || pLocaleItem->m_bModified) &&
999 loadLocale( pLocaleItem.get() ) )
1000 {
1001 OUString aCompleteFileName =
1002 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location );
1003 if( xFileAccess->exists( aCompleteFileName ) )
1004 xFileAccess->kill( aCompleteFileName );
1005
1006 if( !bKillAll )
1007 {
1008 // Create Output stream
1009 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1010 if( xOutputStream.is() )
1011 {
1012 implWritePropertiesFile( pLocaleItem.get(), xOutputStream, aComment );
1013 xOutputStream->closeOutput();
1014 }
1015 if( bUsedForStore )
1016 pLocaleItem->m_bModified = false;
1017 }
1018 }
1019 }
1020
1021 // Delete files for changed defaults
1022 if( bUsedForStore || bKillAll )
1023 implKillChangedDefaultFiles( Location, aNameBase, xFileAccess );
1024
1025 // Default locale
1026 if( !(m_pDefaultLocaleItem != nullptr && (bStoreAll || bKillAll || m_bDefaultModified)) )
1027 return;
1028
1029 OUString aCompleteFileName =
1030 implGetPathForLocaleItem( m_pDefaultLocaleItem, aNameBase, Location, true );
1031 if( xFileAccess->exists( aCompleteFileName ) )
1032 xFileAccess->kill( aCompleteFileName );
1033
1034 if( !bKillAll )
1035 {
1036 // Create Output stream
1037 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1038 if( xOutputStream.is() )
1039 xOutputStream->closeOutput();
1040
1041 if( bUsedForStore )
1042 m_bDefaultModified = false;
1043 }
1044}
1045
1046
1047// BinaryOutput, helper class for exportBinary
1048
1050{
1053
1054public:
1055 explicit BinaryOutput();
1056
1058 { return m_xOutputStream; }
1059
1060 Sequence< ::sal_Int8 > closeAndGetData();
1061
1062 // Template to be used with sal_Int16 and sal_Unicode
1063 template< class T >
1064 void write16BitInt( T n );
1065 void writeInt16( sal_Int16 n )
1066 { write16BitInt( n ); }
1068 { write16BitInt( n ); }
1069 void writeInt32( sal_Int32 n );
1070 void writeString( const OUString& aStr );
1071};
1072
1074{
1077}
1078
1079template< class T >
1081{
1082 if( !m_xOutputStream.is() )
1083 return;
1084
1086 sal_Int8* p = aSeq.getArray();
1087
1088 sal_Int8 nLow = sal_Int8( n & 0xff );
1089 sal_Int8 nHigh = sal_Int8( n >> 8 );
1090
1091 p[0] = nLow;
1092 p[1] = nHigh;
1093 m_xOutputStream->writeBytes( aSeq );
1094}
1095
1096void BinaryOutput::writeInt32( sal_Int32 n )
1097{
1098 if( !m_xOutputStream.is() )
1099 return;
1100
1102 sal_Int8* p = aSeq.getArray();
1103
1104 for( sal_Int16 i = 0 ; i < 4 ; i++ )
1105 {
1106 p[i] = sal_Int8( n & 0xff );
1107 n >>= 8;
1108 }
1109 m_xOutputStream->writeBytes( aSeq );
1110}
1111
1112void BinaryOutput::writeString( const OUString& aStr )
1113{
1114 sal_Int32 nLen = aStr.getLength();
1115 const sal_Unicode* pStr = aStr.getStr();
1116
1117 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1118 writeUnicodeChar( pStr[i] );
1119
1120 writeUnicodeChar( 0 );
1121}
1122
1123Sequence< ::sal_Int8 > BinaryOutput::closeAndGetData()
1124{
1125 Sequence< ::sal_Int8 > aRetSeq;
1126 if( !m_xOutputStream.is() )
1127 return aRetSeq;
1128
1129 m_xOutputStream->closeOutput();
1130
1131 sal_Int32 nSize = static_cast<sal_Int32>(m_xTempFile->getPosition());
1132
1133 m_xTempFile->seek( 0 );
1134 sal_Int32 nRead = m_xTempFile->readBytes( aRetSeq, nSize );
1135 OSL_ENSURE( nRead == nSize, "BinaryOutput::closeAndGetData: nRead != nSize" );
1136
1137 return aRetSeq;
1138}
1139
1140
1141// Binary format:
1142
1143// Header
1144// Byte Content
1145// 0 + 1 sal_Int16: Version, currently 0, low byte first
1146// 2 + 3 sal_Int16: Locale count = n, low byte first
1147// 4 + 5 sal_Int16: Default Locale position in Locale list, == n if none
1148// 6 - 7 sal_Int32: Start index locale block 0, lowest byte first
1149// (n-1) * sal_Int32: Start index locale block 1 to n, lowest byte first
1150// 6 + 4*n sal_Int32: "Start index" non existing locale block n+1,
1151// marks the first invalid index, kind of EOF
1152
1153// Locale block
1154// All strings are stored as 2-Byte-0 terminated sequence
1155// of 16 bit Unicode characters, each with low byte first
1156// Empty strings only contain the 2-Byte-0
1157
1158// Members of com.sun.star.lang.Locale
1159// with l1 = Locale.Language.getLength()
1160// with l2 = Locale.Country.getLength()
1161// with l3 = Locale.Variant.getLength()
1162// pos0 = 0 Locale.Language
1163// pos1 = 2 * (l1 + 1) Locale.Country
1164// pos2 = pos1 + 2 * (l2 + 1) Locale.Variant
1165// pos3 = pos2 + 2 * (l3 + 1)
1166// pos3 Properties file written by implWritePropertiesFile
1167
1169{
1170 BinaryOutput aOut;
1171
1172 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
1173 std::vector<Sequence< sal_Int8 >> aLocaleDataSeq(nLocaleCount);
1174
1175 sal_Int32 iLocale = 0;
1176 sal_Int32 iDefault = 0;
1177 for( auto& pLocaleItem : m_aLocaleItemVector )
1178 {
1179 if( pLocaleItem != nullptr && loadLocale( pLocaleItem.get() ) )
1180 {
1181 if( m_pDefaultLocaleItem == pLocaleItem.get() )
1182 iDefault = iLocale;
1183
1184 BinaryOutput aLocaleOut;
1185 implWriteLocaleBinary( pLocaleItem.get(), aLocaleOut );
1186
1187 aLocaleDataSeq[iLocale] = aLocaleOut.closeAndGetData();
1188 }
1189 ++iLocale;
1190 }
1191
1192 // Write header
1193 sal_Int16 nLocaleCount16 = static_cast<sal_Int16>(nLocaleCount);
1194 sal_Int16 iDefault16 = static_cast<sal_Int16>(iDefault);
1195 aOut.writeInt16( 0 ); // nVersion
1196 aOut.writeInt16( nLocaleCount16 );
1197 aOut.writeInt16( iDefault16 );
1198
1199 // Write data positions
1200 sal_Int32 nDataPos = 6 + 4 * (nLocaleCount + 1);
1201 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1202 {
1203 aOut.writeInt32( nDataPos );
1204
1205 Sequence< sal_Int8 >& rSeq = aLocaleDataSeq[iLocale];
1206 sal_Int32 nSeqLen = rSeq.getLength();
1207 nDataPos += nSeqLen;
1208 }
1209 // Write final position
1210 aOut.writeInt32( nDataPos );
1211
1212 // Write data
1213 Reference< io::XOutputStream > xOutputStream = aOut.getOutputStream();
1214 if( xOutputStream.is() )
1215 {
1216 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1217 {
1218 Sequence< sal_Int8 >& rSeq = aLocaleDataSeq[iLocale];
1219 xOutputStream->writeBytes( rSeq );
1220 }
1221 }
1222
1223 Sequence< sal_Int8 > aRetSeq = aOut.closeAndGetData();
1224 return aRetSeq;
1225}
1226
1228 ( LocaleItem* pLocaleItem, BinaryOutput& rOut )
1229{
1230 Reference< io::XOutputStream > xOutputStream = rOut.getOutputStream();
1231 if( !xOutputStream.is() )
1232 return;
1233
1234 Locale& rLocale = pLocaleItem->m_locale;
1235 rOut.writeString( rLocale.Language );
1236 rOut.writeString( rLocale.Country );
1237 rOut.writeString( rLocale.Variant );
1238 implWritePropertiesFile( pLocaleItem, xOutputStream, m_aComment );
1239}
1240
1241
1242// BinaryOutput, helper class for exportBinary
1243
1244namespace {
1245
1246class BinaryInput
1247{
1249
1251 sal_Int32 m_nCurPos;
1252 sal_Int32 m_nSize;
1253
1254public:
1255 BinaryInput( const Sequence< ::sal_Int8 >& aData );
1256
1257 Reference< io::XInputStream > getInputStreamForSection( sal_Int32 nSize );
1258
1259 void seek( sal_Int32 nPos );
1260 sal_Int32 getPosition() const
1261 { return m_nCurPos; }
1262
1263 sal_Int16 readInt16();
1264 sal_Int32 readInt32();
1265 sal_Unicode readUnicodeChar();
1266 OUString readString();
1267};
1268
1269}
1270
1271BinaryInput::BinaryInput( const Sequence< ::sal_Int8 >& aData )
1272 : m_aData( aData )
1273{
1274 m_pData = m_aData.getConstArray();
1275 m_nCurPos = 0;
1276 m_nSize = m_aData.getLength();
1277}
1278
1279Reference< io::XInputStream > BinaryInput::getInputStreamForSection( sal_Int32 nSize )
1280{
1282 if( m_nCurPos + nSize <= m_nSize )
1283 {
1285 Sequence< sal_Int8 > aSection( m_pData + m_nCurPos, nSize );
1286 xTempOut->writeBytes( aSection );
1287 xTempOut->seek( 0 );
1288 xIn = xTempOut;
1289 }
1290 else
1291 OSL_FAIL( "BinaryInput::getInputStreamForSection(): Read past end" );
1292
1293 return xIn;
1294}
1295
1296void BinaryInput::seek( sal_Int32 nPos )
1297{
1298 if( nPos <= m_nSize )
1299 m_nCurPos = nPos;
1300 else
1301 OSL_FAIL( "BinaryInput::seek(): Position past end" );
1302}
1303
1304
1305sal_Int16 BinaryInput::readInt16()
1306{
1307 sal_Int16 nRet = 0;
1308 if( m_nCurPos + 2 <= m_nSize )
1309 {
1310 nRet = nRet + sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1311 nRet += 256 * sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1312 }
1313 else
1314 OSL_FAIL( "BinaryInput::readInt16(): Read past end" );
1315
1316 return nRet;
1317}
1318
1319sal_Int32 BinaryInput::readInt32()
1320{
1321 sal_Int32 nRet = 0;
1322 if( m_nCurPos + 4 <= m_nSize )
1323 {
1324 sal_Int32 nFactor = 1;
1325 for( sal_Int16 i = 0; i < 4; i++ )
1326 {
1327 nRet += sal_uInt8( m_pData[m_nCurPos++] ) * nFactor;
1328 nFactor *= 256;
1329 }
1330 }
1331 else
1332 OSL_FAIL( "BinaryInput::readInt32(): Read past end" );
1333
1334 return nRet;
1335}
1336
1337sal_Unicode BinaryInput::readUnicodeChar()
1338{
1339 sal_uInt16 nRet = 0;
1340 if( m_nCurPos + 2 <= m_nSize )
1341 {
1342 nRet = nRet + sal_uInt8( m_pData[m_nCurPos++] );
1343 nRet += 256 * sal_uInt8( m_pData[m_nCurPos++] );
1344 }
1345 else
1346 OSL_FAIL( "BinaryInput::readUnicodeChar(): Read past end" );
1347
1348 sal_Unicode cRet = nRet;
1349 return cRet;
1350}
1351
1352OUString BinaryInput::readString()
1353{
1354 OUStringBuffer aBuf;
1355 sal_Unicode c;
1356 do
1357 {
1358 c = readUnicodeChar();
1359 if( c != 0 )
1360 aBuf.append( c );
1361 }
1362 while( c != 0 );
1363
1364 OUString aRetStr = aBuf.makeStringAndClear();
1365 return aRetStr;
1366}
1367
1368void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
1369{
1370 // Init: Remove all locales
1371 sal_Int32 nOldLocaleCount = 0;
1372 do
1373 {
1374 Sequence< Locale > aLocaleSeq = getLocales();
1375 nOldLocaleCount = aLocaleSeq.getLength();
1376 if( nOldLocaleCount > 0 )
1377 {
1378 Locale aLocale = aLocaleSeq[0];
1379 removeLocale( aLocale );
1380 }
1381 }
1382 while( nOldLocaleCount > 0 );
1383
1384 // Import data
1385 BinaryInput aIn( Data );
1386
1387 aIn.readInt16(); // version
1388 sal_Int32 nLocaleCount = aIn.readInt16();
1389 sal_Int32 iDefault = aIn.readInt16();
1390
1391 std::unique_ptr<sal_Int32[]> pPositions( new sal_Int32[nLocaleCount + 1] );
1392 for( sal_Int32 i = 0; i < nLocaleCount + 1; i++ )
1393 pPositions[i] = aIn.readInt32();
1394
1395 // Import locales
1396 LocaleItem* pUseAsDefaultItem = nullptr;
1397 for( sal_Int32 i = 0; i < nLocaleCount; i++ )
1398 {
1399 sal_Int32 nPos = pPositions[i];
1400 aIn.seek( nPos );
1401
1402 Locale aLocale;
1403 aLocale.Language = aIn.readString();
1404 aLocale.Country = aIn.readString();
1405 aLocale.Variant = aIn.readString();
1406
1407 sal_Int32 nAfterStringPos = aIn.getPosition();
1408 sal_Int32 nSize = pPositions[i+1] - nAfterStringPos;
1409 Reference< io::XInputStream > xInput = aIn.getInputStreamForSection( nSize );
1410 if( xInput.is() )
1411 {
1412 LocaleItem* pLocaleItem = new LocaleItem( std::move(aLocale) );
1413 if( iDefault == i )
1414 pUseAsDefaultItem = pLocaleItem;
1415 m_aLocaleItemVector.emplace_back( pLocaleItem );
1416 implReadPropertiesFile( pLocaleItem, xInput );
1417 }
1418 }
1419
1420 if( pUseAsDefaultItem != nullptr )
1421 setDefaultLocale( pUseAsDefaultItem->m_locale );
1422}
1423
1424
1425// Private helper methods
1426
1427static bool checkNamingSceme( std::u16string_view aName, std::u16string_view aNameBase,
1428 Locale& aLocale )
1429{
1430 bool bSuccess = false;
1431
1432 size_t nNameLen = aName.size();
1433 size_t nNameBaseLen = aNameBase.size();
1434
1435 // Name has to start with NameBase followed
1436 // by a '_' and at least one more character
1437 if( o3tl::starts_with(aName, aNameBase) && nNameBaseLen < nNameLen-1 &&
1438 aName[nNameBaseLen] == '_' )
1439 {
1440 bSuccess = true;
1441
1442 /* FIXME-BCP47: this uses '_' underscore character as separator and
1443 * also appends Variant, which can't be blindly changed as it would
1444 * violate the naming scheme in use. */
1445
1446 sal_Int32 iStart = nNameBaseLen + 1;
1447 size_t iNext_ = aName.find( '_', iStart );
1448 if( iNext_ != std::u16string_view::npos && iNext_ < nNameLen-1 )
1449 {
1450 aLocale.Language = aName.substr( iStart, iNext_ - iStart );
1451
1452 iStart = iNext_ + 1;
1453 iNext_ = aName.find( '_', iStart );
1454 if( iNext_ != std::u16string_view::npos && iNext_ < nNameLen-1 )
1455 {
1456 aLocale.Country = aName.substr( iStart, iNext_ - iStart );
1457 aLocale.Variant = aName.substr( iNext_ + 1 );
1458 }
1459 else
1460 aLocale.Country = aName.substr( iStart );
1461 }
1462 else
1463 aLocale.Language = aName.substr( iStart );
1464 }
1465 return bSuccess;
1466}
1467
1468void StringResourcePersistenceImpl::implLoadAllLocales()
1469{
1470 for( auto& pLocaleItem : m_aLocaleItemVector )
1471 if( pLocaleItem )
1472 loadLocale( pLocaleItem.get() );
1473}
1474
1475// Scan locale properties files helper
1476void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< OUString >& aContentSeq )
1477{
1478 Locale aDefaultLocale;
1479 bool bDefaultFound = false;
1480
1481 for( const OUString& aCompleteName : aContentSeq )
1482 {
1483 OUString aPureName;
1484 OUString aExtension;
1485 sal_Int32 iDot = aCompleteName.lastIndexOf( '.' );
1486 sal_Int32 iSlash = aCompleteName.lastIndexOf( '/' );
1487 if( iDot != -1 && iDot > iSlash)
1488 {
1489 sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0;
1490 aPureName = aCompleteName.copy( iCopyFrom, iDot-iCopyFrom );
1491 aExtension = aCompleteName.copy( iDot + 1 );
1492 }
1493
1494 if ( aExtension == "properties" )
1495 {
1496 //OUString aName = aInetObj.getBase();
1497 Locale aLocale;
1498
1499 if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) )
1500 {
1501 LocaleItem* pLocaleItem = new LocaleItem( std::move(aLocale), false );
1502 m_aLocaleItemVector.emplace_back( pLocaleItem );
1503
1504 if( m_pCurrentLocaleItem == nullptr )
1505 m_pCurrentLocaleItem = pLocaleItem;
1506
1507 if( m_pDefaultLocaleItem == nullptr )
1508 {
1509 m_pDefaultLocaleItem = pLocaleItem;
1510 m_bDefaultModified = true;
1511 }
1512 }
1513 }
1514 else if( !bDefaultFound && aExtension == "default" )
1515 {
1516 if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) )
1517 bDefaultFound = true;
1518 }
1519 }
1520 if( bDefaultFound )
1521 {
1522 LocaleItem* pLocaleItem = getItemForLocale( aDefaultLocale, false );
1523 if( pLocaleItem )
1524 {
1525 m_pDefaultLocaleItem = pLocaleItem;
1526 m_bDefaultModified = false;
1527 }
1528 }
1529}
1530
1531// Scan locale properties files
1532void StringResourcePersistenceImpl::implScanLocales()
1533{
1534 // Dummy implementation, method not called for this
1535 // base class, but pure virtual not possible-
1536}
1537
1538bool StringResourcePersistenceImpl::loadLocale( LocaleItem* pLocaleItem )
1539{
1540 bool bSuccess = false;
1541
1542 OSL_ENSURE( pLocaleItem, "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL" );
1543 if( pLocaleItem )
1544 {
1545 if( pLocaleItem->m_bLoaded )
1546 {
1547 bSuccess = true;
1548 }
1549 else
1550 {
1551 bSuccess = implLoadLocale( pLocaleItem );
1552 pLocaleItem->m_bLoaded = true; // = bSuccess??? -> leads to more tries
1553 }
1554 }
1555 return bSuccess;
1556}
1557
1558bool StringResourcePersistenceImpl::implLoadLocale( LocaleItem* )
1559{
1560 // Dummy implementation, method not called for this
1561 // base class, but pure virtual not possible-
1562 return false;
1563}
1564
1565static OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem )
1566{
1567 /* FIXME-BCP47: this uses '_' underscore character as separator and
1568 * also appends Variant, which can't be blindly changed as it would
1569 * violate the naming scheme in use. */
1570
1571 static const char aUnder[] = "_";
1572
1573 OSL_ENSURE( pLocaleItem,
1574 "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL" );
1575 Locale aLocale = pLocaleItem->m_locale;
1576
1577 OUString aRetStr = aUnder + aLocale.Language;
1578
1579 OUString aCountry = aLocale.Country;
1580 if( !aCountry.isEmpty() )
1581 {
1582 aRetStr += aUnder + aCountry;
1583 }
1584
1585 OUString aVariant = aLocale.Variant;
1586 if( !aVariant.isEmpty() )
1587 {
1588 aRetStr += aUnder + aVariant;
1589 }
1590 return aRetStr;
1591}
1592
1593OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem
1594 ( LocaleItem const * pLocaleItem, const OUString& aNameBase )
1595{
1596 OUString aFileName = aNameBase;
1597 if( aFileName.isEmpty() )
1598 aFileName = aNameBaseDefaultStr;
1599
1600 aFileName += implGetNameScemeForLocaleItem( pLocaleItem );
1601 return aFileName;
1602}
1603
1604OUString StringResourcePersistenceImpl::implGetPathForLocaleItem
1605 ( LocaleItem const * pLocaleItem, const OUString& aNameBase,
1606 std::u16string_view aLocation, bool bDefaultFile )
1607{
1608 OUString aFileName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1609 INetURLObject aInetObj( aLocation );
1611 if( bDefaultFile )
1612 aInetObj.setExtension( u"default" );
1613 else
1614 aInetObj.setExtension( u"properties" );
1615 OUString aCompleteFileName = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1616 return aCompleteFileName;
1617}
1618
1619// White space according to Java property files specification in
1620// http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)
1622{
1623 bool bWhite = ( c == 0x0020 || // space
1624 c == 0x0009 || // tab
1625 c == 0x000a || // line feed, not always handled by TextInputStream
1626 c == 0x000d || // carriage return, not always handled by TextInputStream
1627 c == 0x000C ); // form feed
1628 return bWhite;
1629}
1630
1631static void skipWhites( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1632{
1633 while( ri < nLen )
1634 {
1635 if( !isWhiteSpace( pBuf[ri] ) )
1636 break;
1637 ri++;
1638 }
1639}
1640
1641static bool isHexDigit( sal_Unicode c, sal_uInt16& nDigitVal )
1642{
1643 bool bRet = true;
1644 if( c >= '0' && c <= '9' )
1645 nDigitVal = c - '0';
1646 else if( c >= 'a' && c <= 'f' )
1647 nDigitVal = c - 'a' + 10;
1648 else if( c >= 'A' && c <= 'F' )
1649 nDigitVal = c - 'A' + 10;
1650 else
1651 bRet = false;
1652 return bRet;
1653}
1654
1655static sal_Unicode getEscapeChar( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1656{
1657 sal_Int32 i = ri;
1658
1659 sal_Unicode cRet = 0;
1660 sal_Unicode c = pBuf[i];
1661 switch( c )
1662 {
1663 case 't':
1664 cRet = 0x0009;
1665 break;
1666 case 'n':
1667 cRet = 0x000a;
1668 break;
1669 case 'f':
1670 cRet = 0x000c;
1671 break;
1672 case 'r':
1673 cRet = 0x000d;
1674 break;
1675 case '\\':
1676 cRet = '\\';
1677 break;
1678 case 'u':
1679 {
1680 // Skip multiple u
1681 i++;
1682 while( i < nLen && pBuf[i] == 'u' )
1683 i++;
1684
1685 // Process hex digits
1686 sal_Int32 nDigitCount = 0;
1687 sal_uInt16 nDigitVal;
1688 while( i < nLen && isHexDigit( pBuf[i], nDigitVal ) )
1689 {
1690 cRet = 16 * cRet + nDigitVal;
1691
1692 nDigitCount++;
1693 if( nDigitCount == 4 )
1694 {
1695 // Write back position
1696 ri = i;
1697 break;
1698 }
1699 i++;
1700 }
1701 break;
1702 }
1703 default:
1704 cRet = c;
1705 }
1706
1707 return cRet;
1708}
1709
1710static void CheckContinueInNextLine( const Reference< io::XTextInputStream2 >& xTextInputStream,
1711 OUString& aLine, bool& bEscapePending, const sal_Unicode*& pBuf,
1712 sal_Int32& nLen, sal_Int32& i )
1713{
1714 if( !(i == nLen && bEscapePending) )
1715 return;
1716
1717 bEscapePending = false;
1718
1719 if( !xTextInputStream->isEOF() )
1720 {
1721 aLine = xTextInputStream->readLine();
1722 nLen = aLine.getLength();
1723 pBuf = aLine.getStr();
1724 i = 0;
1725
1726 skipWhites( pBuf, nLen, i );
1727 }
1728}
1729
1730bool StringResourcePersistenceImpl::implReadPropertiesFile
1731 ( LocaleItem* pLocaleItem, const Reference< io::XInputStream >& xInputStream )
1732{
1733 if( !xInputStream.is() || pLocaleItem == nullptr )
1734 return false;
1735
1736 Reference< io::XTextInputStream2 > xTextInputStream = io::TextInputStream::create( m_xContext );
1737
1738 xTextInputStream->setInputStream( xInputStream );
1739
1740 OUString aEncodingStr = OUString::createFromAscii
1741 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
1742 xTextInputStream->setEncoding( aEncodingStr );
1743
1744 OUString aLine;
1745 while( !xTextInputStream->isEOF() )
1746 {
1747 aLine = xTextInputStream->readLine();
1748
1749 sal_Int32 nLen = aLine.getLength();
1750 if( 0 == nLen )
1751 continue;
1752 const sal_Unicode* pBuf = aLine.getStr();
1753 OUStringBuffer aBuf;
1754 sal_Unicode c = 0;
1755 sal_Int32 i = 0;
1756
1757 skipWhites( pBuf, nLen, i );
1758 if( i == nLen )
1759 continue; // line contains only white spaces
1760
1761 // Comment?
1762 c = pBuf[i];
1763 if( c == '#' || c == '!' )
1764 continue;
1765
1766 // Scan key
1767 OUString aResourceID;
1768 bool bEscapePending = false;
1769 bool bStrComplete = false;
1770 while( i < nLen && !bStrComplete )
1771 {
1772 c = pBuf[i];
1773 if( bEscapePending )
1774 {
1775 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
1776 bEscapePending = false;
1777 }
1778 else
1779 {
1780 if( c == '\\' )
1781 {
1782 bEscapePending = true;
1783 }
1784 else
1785 {
1786 if( c == ':' || c == '=' || isWhiteSpace( c ) )
1787 bStrComplete = true;
1788 else
1789 aBuf.append( c );
1790 }
1791 }
1792 i++;
1793
1794 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
1795 if( i == nLen )
1796 bStrComplete = true;
1797
1798 if( bStrComplete )
1799 aResourceID = aBuf.makeStringAndClear();
1800 }
1801
1802 // Ignore lines with empty keys
1803 if( aResourceID.isEmpty() )
1804 continue;
1805
1806 // Scan value
1807 skipWhites( pBuf, nLen, i );
1808
1809 OUString aValueStr;
1810 bEscapePending = false;
1811 bStrComplete = false;
1812 while( i < nLen && !bStrComplete )
1813 {
1814 c = pBuf[i];
1815 if( c == 0x000a || c == 0x000d ) // line feed/carriage return, not always handled by TextInputStream
1816 {
1817 i++;
1818 }
1819 else
1820 {
1821 if( bEscapePending )
1822 {
1823 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
1824 bEscapePending = false;
1825 }
1826 else if( c == '\\' )
1827 bEscapePending = true;
1828 else
1829 aBuf.append( c );
1830 i++;
1831
1832 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
1833 }
1834 if( i == nLen )
1835 bStrComplete = true;
1836
1837 if( bStrComplete )
1838 aValueStr = aBuf.makeStringAndClear();
1839 }
1840
1841 // Push into table
1842 pLocaleItem->m_aIdToStringMap[ aResourceID ] = aValueStr;
1843 implScanIdForNumber( aResourceID );
1844 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
1845 rIndexMap[ aResourceID ] = pLocaleItem->m_nNextIndex++;
1846 }
1847
1848 return true;
1849}
1850
1851
1852static sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal )
1853{
1854 sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10));
1855 return cRet;
1856}
1857
1858static void implWriteCharToBuffer( OUStringBuffer& aBuf, sal_Unicode cu, bool bKey )
1859{
1860 if( cu == '\\' )
1861 {
1862 aBuf.append( '\\' );
1863 aBuf.append( '\\' );
1864 }
1865 else if( cu == 0x000a )
1866 {
1867 aBuf.append( '\\' );
1868 aBuf.append( 'n' );
1869 }
1870 else if( cu == 0x000d )
1871 {
1872 aBuf.append( '\\' );
1873 aBuf.append( 'r' );
1874 }
1875 else if( bKey && cu == '=' )
1876 {
1877 aBuf.append( '\\' );
1878 aBuf.append( '=' );
1879 }
1880 else if( bKey && cu == ':' )
1881 {
1882 aBuf.append( '\\' );
1883 aBuf.append( ':' );
1884 }
1885 // ISO/IEC 8859-1 range according to:
1886 // http://en.wikipedia.org/wiki/ISO/IEC_8859-1
1887 else if( cu >= 0x20 && cu <= 0x7e )
1888 //TODO: Check why (cu >= 0xa0 && cu <= 0xFF)
1889 //is encoded in sample properties files
1890 //else if( (cu >= 0x20 && cu <= 0x7e) ||
1891 // (cu >= 0xa0 && cu <= 0xFF) )
1892 {
1893 aBuf.append( cu );
1894 }
1895 else
1896 {
1897 // Unicode encoding
1898 aBuf.append( '\\' );
1899 aBuf.append( 'u' );
1900
1901 sal_uInt16 nVal = cu;
1902 for( sal_uInt16 i = 0 ; i < 4 ; i++ )
1903 {
1904 sal_uInt16 nDigit = nVal / 0x1000;
1905 nVal -= nDigit * 0x1000;
1906 nVal *= 0x10;
1907 aBuf.append( getHexCharForDigit( nDigit ) );
1908 }
1909 }
1910}
1911
1912static void implWriteStringWithEncoding( const OUString& aStr,
1913 Reference< io::XTextOutputStream2 > const & xTextOutputStream, bool bKey )
1914{
1915 static const sal_Unicode cLineFeed = 0xa;
1916
1917 OUStringBuffer aBuf;
1918 sal_Int32 nLen = aStr.getLength();
1919 const sal_Unicode* pSrc = aStr.getStr();
1920 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1921 {
1922 sal_Unicode cu = pSrc[i];
1923 implWriteCharToBuffer( aBuf, cu, bKey );
1924 // TODO?: split long lines
1925 }
1926 if( !bKey )
1927 aBuf.append( cLineFeed );
1928
1929 OUString aWriteStr = aBuf.makeStringAndClear();
1930 xTextOutputStream->writeString( aWriteStr );
1931}
1932
1933bool StringResourcePersistenceImpl::implWritePropertiesFile( LocaleItem const * pLocaleItem,
1934 const Reference< io::XOutputStream >& xOutputStream, const OUString& aComment )
1935{
1936 if( !xOutputStream.is() || pLocaleItem == nullptr )
1937 return false;
1938
1939 bool bSuccess = false;
1940 Reference< io::XTextOutputStream2 > xTextOutputStream = io::TextOutputStream::create(m_xContext);
1941
1942 xTextOutputStream->setOutputStream( xOutputStream );
1943
1944 OUString aEncodingStr = OUString::createFromAscii
1945 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
1946 xTextOutputStream->setEncoding( aEncodingStr );
1947
1948 xTextOutputStream->writeString( aComment );
1949 xTextOutputStream->writeString( "\n" );
1950
1951 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
1952 if( !rHashMap.empty() )
1953 {
1954 // Sort ids according to read order
1955 const IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
1956
1957 // Find max/min index
1958 auto itMinMax = std::minmax_element(rIndexMap.begin(), rIndexMap.end(),
1959 [](const IdToIndexMap::value_type& a, const IdToIndexMap::value_type& b) { return a.second < b.second; });
1960 sal_Int32 nMinIndex = itMinMax.first->second;
1961 sal_Int32 nMaxIndex = itMinMax.second->second;
1962 sal_Int32 nTabSize = nMaxIndex - nMinIndex + 1;
1963
1964 // Create sorted array of pointers to the id strings
1965 std::unique_ptr<const OUString*[]> pIdPtrs( new const OUString*[nTabSize] );
1966 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
1967 pIdPtrs[i] = nullptr;
1968 for( const auto& rIndex : rIndexMap )
1969 {
1970 sal_Int32 nIndex = rIndex.second;
1971 pIdPtrs[nIndex - nMinIndex] = &(rIndex.first);
1972 }
1973
1974 // Write lines in correct order
1975 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
1976 {
1977 const OUString* pStr = pIdPtrs[i];
1978 if( pStr != nullptr )
1979 {
1980 OUString aResourceID = *pStr;
1981 IdToStringMap::const_iterator it = rHashMap.find( aResourceID );
1982 if( it != rHashMap.end() )
1983 {
1984 implWriteStringWithEncoding( aResourceID, xTextOutputStream, true );
1985 xTextOutputStream->writeString( "=" );
1986 OUString aValStr = (*it).second;
1987 implWriteStringWithEncoding( aValStr, xTextOutputStream, false );
1988 }
1989 }
1990 }
1991 }
1992
1993 bSuccess = true;
1994
1995 return bSuccess;
1996}
1997
1998
1999// StringResourceWithStorageImpl
2000
2001extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2003 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
2004{
2005 return cppu::acquire(new StringResourceWithStorageImpl(context));
2006}
2007
2008
2009StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext )
2011 , m_bStorageChanged( false )
2012{
2013}
2014
2015
2017{
2018}
2019
2020
2021// XServiceInfo
2022
2023
2025{
2026 return "com.sun.star.comp.scripting.StringResourceWithStorage";
2027}
2028
2030{
2031 return cppu::supportsService(this, rServiceName);
2032}
2033
2035{
2036 return { "com.sun.star.resource.StringResourceWithStorage" };
2037}
2038
2039
2040// XInitialization
2041
2042
2043void StringResourceWithStorageImpl::initialize( const Sequence< Any >& aArguments )
2044{
2045 std::unique_lock aGuard( m_aMutex );
2046
2047 if ( aArguments.getLength() != 5 )
2048 {
2049 throw RuntimeException(
2050 "StringResourceWithStorageImpl::initialize: invalid number of arguments!" );
2051 }
2052
2053 bool bOk = (aArguments[0] >>= m_xStorage);
2054 if( bOk && !m_xStorage.is() )
2055 bOk = false;
2056
2057 if( !bOk )
2058 {
2059 throw IllegalArgumentException( "StringResourceWithStorageImpl::initialize: invalid storage", Reference< XInterface >(), 0 );
2060 }
2061
2062 implInitializeCommonParameters( aGuard, aArguments );
2063}
2064
2065
2066// Forwarding calls to base class
2067
2068// XModifyBroadcaster
2069void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2070{
2072}
2073void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2074{
2076}
2077
2078// XStringResourceResolver
2079OUString StringResourceWithStorageImpl::resolveString( const OUString& ResourceID )
2080{
2081 return StringResourceImpl::resolveString( ResourceID ) ;
2082}
2083OUString StringResourceWithStorageImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2084{
2085 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2086}
2088{
2089 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2090}
2092 const Locale& locale )
2093{
2094 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2095}
2097{
2099}
2101 ( const Locale& locale )
2102{
2104}
2106{
2108}
2110{
2112}
2114{
2116}
2117
2118// XStringResourceManager
2120{
2122}
2123void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2124{
2125 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2126}
2128{
2130}
2131void StringResourceWithStorageImpl::setString( const OUString& ResourceID, const OUString& Str )
2132{
2133 StringResourceImpl::setString( ResourceID, Str );
2134}
2136 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2137{
2138 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2139}
2140void StringResourceWithStorageImpl::removeId( const OUString& ResourceID )
2141{
2142 StringResourceImpl::removeId( ResourceID );
2143}
2144void StringResourceWithStorageImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2145{
2146 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2147}
2149{
2151}
2153{
2155}
2157{
2159}
2160
2161// XStringResourcePersistence
2163{
2164 std::unique_lock aGuard( m_aMutex );
2165 implCheckReadOnly( "StringResourceWithStorageImpl::store(): Read only" );
2166
2167 bool bStoreAll = m_bStorageChanged;
2168 m_bStorageChanged = false;
2169 if( !m_bModified && !bStoreAll )
2170 return;
2171
2172 implStoreAtStorage( m_aNameBase, m_aComment, m_xStorage, true/*bUsedForStore*/, bStoreAll );
2173 m_bModified = false;
2174}
2175
2177{
2179}
2180void StringResourceWithStorageImpl::setComment( const OUString& Comment )
2181{
2183}
2184void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage,
2185 const OUString& NameBase, const OUString& Comment )
2186{
2188}
2190 const OUString& NameBase, const OUString& Comment,
2191 const Reference< css::task::XInteractionHandler >& Handler )
2192{
2194}
2196{
2198}
2199void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2200{
2202}
2203
2204
2205// XStringResourceWithStorage
2206
2207void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage )
2208{
2210 store();
2211}
2212
2213void StringResourceWithStorageImpl::setStorage( const Reference< XStorage >& Storage )
2214{
2215 std::unique_lock aGuard( m_aMutex );
2216
2217 if( !Storage.is() )
2218 {
2219 throw IllegalArgumentException( "StringResourceWithStorageImpl::setStorage: invalid storage", Reference< XInterface >(), 0 );
2220 }
2221
2222 implLoadAllLocales();
2223
2225 m_bStorageChanged = true;
2226}
2227
2228
2229// Private helper methods
2230
2231
2232// Scan locale properties files
2234{
2235 if( m_xStorage.is() )
2236 {
2237 Sequence< OUString > aContentSeq = m_xStorage->getElementNames();
2238 implScanLocaleNames( aContentSeq );
2239 }
2240
2241 implLoadAllLocales();
2242}
2243
2244// Loading
2246{
2247 bool bSuccess = false;
2248 try
2249 {
2250 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase ) + ".properties";
2251
2252 Reference< io::XStream > xElementStream =
2253 m_xStorage->openStreamElement( aStreamName, ElementModes::READ );
2254
2255 if( xElementStream.is() )
2256 {
2257 Reference< io::XInputStream > xInputStream = xElementStream->getInputStream();
2258 if( xInputStream.is() )
2259 {
2260 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2261 xInputStream->closeInput();
2262 }
2263 }
2264 }
2265 catch( uno::Exception& )
2266 {}
2267
2268 return bSuccess;
2269}
2270
2271
2272// StringResourceWithLocationImpl
2273
2274
2275extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2277 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
2278{
2279 return cppu::acquire(new StringResourceWithLocationImpl(context));
2280}
2281
2282
2283
2284StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext )
2286 , m_bLocationChanged( false )
2287{
2288}
2289
2290
2292{
2293}
2294
2295
2296// XServiceInfo
2297
2298
2300{
2301 return "com.sun.star.comp.scripting.StringResourceWithLocation";
2302}
2303
2305{
2306 return cppu::supportsService(this, rServiceName);
2307}
2308
2310{
2311 return { "com.sun.star.resource.StringResourceWithLocation" };
2312}
2313
2314
2315// XInitialization
2316
2317
2318void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArguments )
2319{
2320 std::unique_lock aGuard( m_aMutex );
2321
2322 if ( aArguments.getLength() != 6 )
2323 {
2324 throw RuntimeException(
2325 "XInitialization::initialize: invalid number of arguments!" );
2326 }
2327
2328 bool bOk = (aArguments[0] >>= m_aLocation);
2329 sal_Int32 nLen = m_aLocation.getLength();
2330 if( bOk && nLen == 0 )
2331 {
2332 bOk = false;
2333 }
2334 else
2335 {
2336 if( m_aLocation[nLen - 1] != '/' )
2337 m_aLocation += "/";
2338 }
2339
2340 if( !bOk )
2341 {
2342 throw IllegalArgumentException( "XInitialization::initialize: invalid URL", Reference< XInterface >(), 0 );
2343 }
2344
2345
2346 bOk = (aArguments[5] >>= m_xInteractionHandler);
2347 if( !bOk )
2348 {
2349 throw IllegalArgumentException( "StringResourceWithStorageImpl::initialize: invalid type", Reference< XInterface >(), 5 );
2350 }
2351
2352 implInitializeCommonParameters( aGuard, aArguments );
2353}
2354
2355
2356// Forwarding calls to base class
2357
2358// XModifyBroadcaster
2359void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2360{
2362}
2363void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2364{
2366}
2367
2368// XStringResourceResolver
2369OUString StringResourceWithLocationImpl::resolveString( const OUString& ResourceID )
2370{
2371 return StringResourceImpl::resolveString( ResourceID ) ;
2372}
2373OUString StringResourceWithLocationImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2374{
2375 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2376}
2378{
2379 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2380}
2382 const Locale& locale )
2383{
2384 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2385}
2387{
2389}
2391 ( const Locale& locale )
2392{
2394}
2396{
2398}
2400{
2402}
2404{
2406}
2407
2408// XStringResourceManager
2410{
2412}
2413void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2414{
2415 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2416}
2418{
2420}
2421void StringResourceWithLocationImpl::setString( const OUString& ResourceID, const OUString& Str )
2422{
2423 StringResourceImpl::setString( ResourceID, Str );
2424}
2426 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2427{
2428 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2429}
2430void StringResourceWithLocationImpl::removeId( const OUString& ResourceID )
2431{
2432 StringResourceImpl::removeId( ResourceID );
2433}
2434void StringResourceWithLocationImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2435{
2436 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2437}
2439{
2441}
2443{
2445}
2447{
2449}
2450
2451// XStringResourcePersistence
2453{
2454 std::unique_lock aGuard( m_aMutex );
2455 implCheckReadOnly( "StringResourceWithLocationImpl::store(): Read only" );
2456
2457 bool bStoreAll = m_bLocationChanged;
2458 m_bLocationChanged = false;
2459 if( !m_bModified && !bStoreAll )
2460 return;
2461
2462 Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccessImpl();
2463 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2464 xFileAccess, true/*bUsedForStore*/, bStoreAll );
2465 m_bModified = false;
2466}
2467
2469{
2471}
2472void StringResourceWithLocationImpl::setComment( const OUString& Comment )
2473{
2475}
2476void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage,
2477 const OUString& NameBase, const OUString& Comment )
2478{
2480}
2482 const OUString& NameBase, const OUString& Comment,
2483 const Reference< css::task::XInteractionHandler >& Handler )
2484{
2486}
2488{
2490}
2491void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2492{
2494}
2495
2496
2497// XStringResourceWithLocation
2498
2499// XStringResourceWithLocation
2501{
2502 setURL( URL );
2503 store();
2504}
2505
2507{
2508 std::unique_lock aGuard( m_aMutex );
2509 implCheckReadOnly( "StringResourceWithLocationImpl::setURL(): Read only" );
2510
2511 sal_Int32 nLen = URL.getLength();
2512 if( nLen == 0 )
2513 {
2514 throw IllegalArgumentException( "StringResourceWithLocationImpl::setURL: invalid URL", Reference< XInterface >(), 0 );
2515 }
2516
2517 implLoadAllLocales();
2518
2519 // Delete files at old location
2520 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2521 getFileAccessImpl(), false/*bUsedForStore*/, false/*bStoreAll*/, true/*bKillAll*/ );
2522
2523 m_aLocation = URL;
2524 m_bLocationChanged = true;
2525}
2526
2527
2528// Private helper methods
2529
2530
2531// Scan locale properties files
2533{
2534 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccessImpl();
2535 if( xFileAccess.is() && xFileAccess->isFolder( m_aLocation ) )
2536 {
2537 Sequence< OUString > aContentSeq = xFileAccess->getFolderContents( m_aLocation, false );
2538 implScanLocaleNames( aContentSeq );
2539 }
2540}
2541
2542// Loading
2544{
2545 bool bSuccess = false;
2546
2547 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccessImpl();
2548 if( xFileAccess.is() )
2549 {
2550 OUString aCompleteFileName =
2551 implGetPathForLocaleItem( pLocaleItem, m_aNameBase, m_aLocation );
2552
2553 Reference< io::XInputStream > xInputStream;
2554 try
2555 {
2556 xInputStream = xFileAccess->openFileRead( aCompleteFileName );
2557 }
2558 catch( Exception& )
2559 {}
2560 if( xInputStream.is() )
2561 {
2562 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2563 xInputStream->closeInput();
2564 }
2565 }
2566
2567 return bSuccess;
2568}
2569
2570const Reference< ucb::XSimpleFileAccess3 > & StringResourceWithLocationImpl::getFileAccessImpl()
2571{
2572 if( !m_xSFI.is() )
2573 {
2574 m_xSFI = ucb::SimpleFileAccess::create(m_xContext);
2575
2576 if( m_xSFI.is() && m_xInteractionHandler.is() )
2577 m_xSFI->setInteractionHandler( m_xInteractionHandler );
2578 }
2579 return m_xSFI;
2580}
2581
2582} // namespace stringresource
2583
2584
2585/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
AnyEventRef aEvent
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
bool insertName(std::u16string_view rTheName, bool bAppendFinalSlash=false, sal_Int32 nIndex=LAST_SEGMENT, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
bool setExtension(std::u16string_view rTheExtension, sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
::std::vector< css::lang::Locale >::const_iterator getMatchingFallback(const ::std::vector< css::lang::Locale > &rList, const css::lang::Locale &rReference)
void forEach(std::unique_lock< std::mutex > &rGuard, FuncT const &func) const
sal_Int32 addInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
sal_Int32 removeInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
Reference< io::XOutputStream > m_xOutputStream
Sequence< ::sal_Int8 > closeAndGetData()
rtl::Reference< utl::TempFileFastService > m_xTempFile
const Reference< io::XOutputStream > & getOutputStream() const
void writeString(const OUString &aStr)
void writeUnicodeChar(sal_Unicode n)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL removeLocale(const css::lang::Locale &locale) override
void implRemoveId(std::unique_lock< std::mutex > &rGuard, const OUString &ResourceID, LocaleItem *pLocaleItem)
virtual bool loadLocale(LocaleItem *pLocaleItem)
StringResourceImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
void implCheckReadOnly(const char *pExceptionMsg)
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
css::uno::Sequence< OUString > implGetResourceIDs(LocaleItem *pLocaleItem)
virtual void SAL_CALL newLocale(const css::lang::Locale &locale) override
std::vector< std::unique_ptr< LocaleItem > > m_aChangedDefaultLocaleVector
LocaleItem * getClosestMatchItemForLocale(const css::lang::Locale &locale)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::lang::Locale SAL_CALL getCurrentLocale() override
void implScanIdForNumber(const OUString &ResourceID)
void implSetCurrentLocale(std::unique_lock< std::mutex > &rGuard, const css::lang::Locale &locale, bool FindClosestMatch, bool bUseDefaultIfNoMatch)
virtual void SAL_CALL setString(const OUString &ResourceID, const OUString &Str) override
void implModified(std::unique_lock< std::mutex > &)
void implNotifyListeners(std::unique_lock< std::mutex > &)
virtual sal_Bool SAL_CALL hasEntryForId(const OUString &ResourceID) override
bool implHasEntryForId(const OUString &ResourceID, LocaleItem *pLocaleItem)
virtual ::sal_Int32 SAL_CALL getUniqueNumericId() override
std::vector< std::unique_ptr< LocaleItem > > m_aDeletedLocaleItemVector
virtual sal_Bool SAL_CALL isReadOnly() override
void implSetString(std::unique_lock< std::mutex > &rGuard, const OUString &ResourceID, const OUString &Str, LocaleItem *pLocaleItem)
std::vector< std::unique_ptr< LocaleItem > > m_aLocaleItemVector
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getLocales() override
virtual css::lang::Locale SAL_CALL getDefaultLocale() override
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
OUString implResolveString(const OUString &ResourceID, LocaleItem *pLocaleItem)
static const sal_Int32 UNIQUE_NUMBER_NEEDS_INITIALISATION
LocaleItem * getItemForLocale(const css::lang::Locale &locale, bool bException)
virtual void SAL_CALL setDefaultLocale(const css::lang::Locale &locale) override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDs() override
virtual sal_Bool SAL_CALL hasEntryForIdAndLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
::comphelper::OInterfaceContainerHelper4< css::util::XModifyListener > m_aListenerContainer
virtual OUString SAL_CALL resolveString(const OUString &ResourceID) override
virtual void SAL_CALL setStringForLocale(const OUString &ResourceID, const OUString &Str, const css::lang::Locale &locale) override
virtual void SAL_CALL setCurrentLocale(const css::lang::Locale &locale, sal_Bool FindClosestMatch) override
virtual OUString SAL_CALL resolveStringForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL removeId(const OUString &ResourceID) override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDsForLocale(const css::lang::Locale &locale) override
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL removeIdForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDs() override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDsForLocale(const css::lang::Locale &locale) override
void implKillRemovedLocaleFiles(std::u16string_view Location, const OUString &aNameBase, const css::uno::Reference< css::ucb::XSimpleFileAccess3 > &xFileAccess)
void implKillChangedDefaultFiles(std::u16string_view Location, const OUString &aNameBase, const css::uno::Reference< css::ucb::XSimpleFileAccess3 > &xFileAccess)
virtual void SAL_CALL storeToURL(const OUString &URL, const OUString &NameBase, const OUString &Comment, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual void SAL_CALL store() override
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getLocales() override
void implStoreAtStorage(const OUString &aNameBase, const OUString &aComment, const css::uno::Reference< css::embed::XStorage > &Storage, bool bUsedForStore, bool bStoreAll)
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL exportBinary() override
virtual ::sal_Int32 SAL_CALL getUniqueNumericId() override
virtual OUString SAL_CALL resolveStringForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL setDefaultLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL setCurrentLocale(const css::lang::Locale &locale, sal_Bool FindClosestMatch) override
virtual void SAL_CALL storeToStorage(const css::uno::Reference< css::embed::XStorage > &Storage, const OUString &NameBase, const OUString &Comment) override
virtual bool loadLocale(LocaleItem *pLocaleItem) override
virtual css::lang::Locale SAL_CALL getCurrentLocale() override
void implStoreAtLocation(std::u16string_view Location, const OUString &aNameBase, const OUString &aComment, const css::uno::Reference< css::ucb::XSimpleFileAccess3 > &xFileAccess, bool bUsedForStore, bool bStoreAll, bool bKillAll=false)
virtual sal_Bool SAL_CALL isModified() override
static OUString implGetFileNameForLocaleItem(LocaleItem const *pLocaleItem, const OUString &aNameBase)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void implInitializeCommonParameters(std::unique_lock< std::mutex > &rGuard, const css::uno::Sequence< css::uno::Any > &aArguments)
virtual void SAL_CALL setString(const OUString &ResourceID, const OUString &Str) override
virtual OUString SAL_CALL getImplementationName() override
virtual sal_Bool SAL_CALL hasEntryForIdAndLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL removeIdForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL removeLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL removeId(const OUString &ResourceID) override
virtual OUString SAL_CALL resolveString(const OUString &ResourceID) override
bool implWritePropertiesFile(LocaleItem const *pLocaleItem, const css::uno::Reference< css::io::XOutputStream > &xOutputStream, const OUString &aComment)
void implWriteLocaleBinary(LocaleItem *pLocaleItem, BinaryOutput &rOut)
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual css::lang::Locale SAL_CALL getDefaultLocale() override
virtual void SAL_CALL newLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL setComment(const OUString &Comment) override
static OUString implGetPathForLocaleItem(LocaleItem const *pLocaleItem, const OUString &aNameBase, std::u16string_view aLocation, bool bDefaultFile=false)
bool implReadPropertiesFile(LocaleItem *pLocaleItem, const css::uno::Reference< css::io::XInputStream > &xInput)
virtual sal_Bool SAL_CALL isReadOnly() override
virtual void SAL_CALL setStringForLocale(const OUString &ResourceID, const OUString &Str, const css::lang::Locale &locale) override
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual sal_Bool SAL_CALL hasEntryForId(const OUString &ResourceID) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL importBinary(const css::uno::Sequence< ::sal_Int8 > &Data) override
StringResourcePersistenceImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual void SAL_CALL setComment(const OUString &Comment) override
css::uno::Reference< css::task::XInteractionHandler > m_xInteractionHandler
virtual sal_Bool SAL_CALL hasEntryForIdAndLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL setCurrentLocale(const css::lang::Locale &locale, sal_Bool FindClosestMatch) override
virtual bool implLoadLocale(LocaleItem *pLocaleItem) override
virtual void SAL_CALL setStringForLocale(const OUString &ResourceID, const OUString &Str, const css::lang::Locale &locale) override
virtual sal_Bool SAL_CALL hasEntryForId(const OUString &ResourceID) override
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual void SAL_CALL removeLocale(const css::lang::Locale &locale) override
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
virtual void SAL_CALL removeId(const OUString &ResourceID) override
virtual void SAL_CALL setString(const OUString &ResourceID, const OUString &Str) override
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getLocales() override
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
const css::uno::Reference< css::ucb::XSimpleFileAccess3 > & getFileAccessImpl()
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDs() override
virtual void SAL_CALL storeToStorage(const css::uno::Reference< css::embed::XStorage > &Storage, const OUString &NameBase, const OUString &Comment) override
virtual css::lang::Locale SAL_CALL getDefaultLocale() override
virtual OUString SAL_CALL resolveStringForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL exportBinary() override
virtual void SAL_CALL importBinary(const css::uno::Sequence< ::sal_Int8 > &Data) override
css::uno::Reference< css::ucb::XSimpleFileAccess3 > m_xSFI
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDsForLocale(const css::lang::Locale &locale) override
virtual css::lang::Locale SAL_CALL getCurrentLocale() override
virtual void SAL_CALL storeToURL(const OUString &URL, const OUString &NameBase, const OUString &Comment, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual ::sal_Int32 SAL_CALL getUniqueNumericId() override
virtual OUString SAL_CALL resolveString(const OUString &ResourceID) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL setURL(const OUString &URL) override
virtual void SAL_CALL newLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL storeAsURL(const OUString &URL) override
virtual sal_Bool SAL_CALL isModified() override
virtual void SAL_CALL removeIdForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
StringResourceWithLocationImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual sal_Bool SAL_CALL isReadOnly() override
virtual void SAL_CALL setDefaultLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual void SAL_CALL setStorage(const css::uno::Reference< css::embed::XStorage > &Storage) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Bool SAL_CALL hasEntryForId(const OUString &ResourceID) override
virtual void SAL_CALL removeIdForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL setString(const OUString &ResourceID, const OUString &Str) override
virtual bool implLoadLocale(LocaleItem *pLocaleItem) override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDs() override
virtual sal_Bool SAL_CALL isModified() override
virtual OUString SAL_CALL resolveStringForLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual void SAL_CALL removeLocale(const css::lang::Locale &locale) override
virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL exportBinary() override
virtual OUString SAL_CALL getImplementationName() override
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getLocales() override
virtual void SAL_CALL setDefaultLocale(const css::lang::Locale &locale) override
virtual sal_Bool SAL_CALL hasEntryForIdAndLocale(const OUString &ResourceID, const css::lang::Locale &locale) override
virtual ::sal_Int32 SAL_CALL getUniqueNumericId() override
virtual void SAL_CALL storeAsStorage(const css::uno::Reference< css::embed::XStorage > &Storage) override
virtual void SAL_CALL setStringForLocale(const OUString &ResourceID, const OUString &Str, const css::lang::Locale &locale) override
virtual css::uno::Sequence< OUString > SAL_CALL getResourceIDsForLocale(const css::lang::Locale &locale) override
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual OUString SAL_CALL resolveString(const OUString &ResourceID) override
virtual sal_Bool SAL_CALL isReadOnly() override
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
css::uno::Reference< css::embed::XStorage > m_xStorage
virtual void SAL_CALL setCurrentLocale(const css::lang::Locale &locale, sal_Bool FindClosestMatch) override
virtual void SAL_CALL removeId(const OUString &ResourceID) override
virtual void SAL_CALL storeToURL(const OUString &URL, const OUString &NameBase, const OUString &Comment, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual void SAL_CALL store() override
virtual void SAL_CALL newLocale(const css::lang::Locale &locale) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL storeToStorage(const css::uno::Reference< css::embed::XStorage > &Storage, const OUString &NameBase, const OUString &Comment) override
virtual css::lang::Locale SAL_CALL getCurrentLocale() override
virtual css::lang::Locale SAL_CALL getDefaultLocale() override
virtual void SAL_CALL importBinary(const css::uno::Sequence< ::sal_Int8 > &Data) override
virtual void SAL_CALL setComment(const OUString &Comment) override
float u
std::mutex m_aMutex
bool m_bReadOnly
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
OUString aName
void * p
sal_Int64 n
uno_Any a
sal_uInt16 nPos
Sequence< sal_Int8 > aSeq
aStr
aBuf
constexpr OUStringLiteral aData
@ Exception
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
OUString aPropName
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
static sal_Unicode getEscapeChar(const sal_Unicode *pBuf, sal_Int32 nLen, sal_Int32 &ri)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * scripting_StringResourcePersistenceImpl_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * scripting_StringResourceWithStorageImpl_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
static bool checkNamingSceme(std::u16string_view aName, std::u16string_view aNameBase, Locale &aLocale)
static OUString implGetNameScemeForLocaleItem(const LocaleItem *pLocaleItem)
static void implWriteCharToBuffer(OUStringBuffer &aBuf, sal_Unicode cu, bool bKey)
::cppu::ImplInheritanceHelper< StringResourceImpl, css::resource::XStringResourcePersistence > StringResourcePersistenceImpl_BASE
static sal_Unicode getHexCharForDigit(sal_uInt16 nDigitVal)
static void skipWhites(const sal_Unicode *pBuf, sal_Int32 nLen, sal_Int32 &ri)
std::unordered_map< OUString, sal_Int32 > IdToIndexMap
::cppu::ImplInheritanceHelper< StringResourcePersistenceImpl, css::lang::XInitialization, css::resource::XStringResourceWithLocation > StringResourceWithLocationImpl_BASE
constexpr OUStringLiteral aNameBaseDefaultStr
static void implWriteStringWithEncoding(const OUString &aStr, Reference< io::XTextOutputStream2 > const &xTextOutputStream, bool bKey)
std::unordered_map< OUString, OUString > IdToStringMap
static bool isWhiteSpace(sal_Unicode c)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * scripting_StringResourceWithLocationImpl_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
static void CheckContinueInNextLine(const Reference< io::XTextInputStream2 > &xTextInputStream, OUString &aLine, bool &bEscapePending, const sal_Unicode *&pBuf, sal_Int32 &nLen, sal_Int32 &i)
::cppu::ImplInheritanceHelper< StringResourcePersistenceImpl, css::lang::XInitialization, css::resource::XStringResourceWithStorage > StringResourceWithStorageImpl_BASE
static bool isHexDigit(sal_Unicode c, sal_uInt16 &nDigitVal)
const size_t nTabSize
sal_uInt32 readString(const sal_uInt8 *buffer, sal_Unicode *v, sal_uInt32 maxSize)
sal_Int32 m_nSize
Sequence< sal_Int8 > m_aData
sal_Int32 m_nCurPos
const sal_Int8 * m_pData
css::lang::Locale m_locale
unsigned char sal_uInt8
unsigned char sal_Bool
sal_uInt16 sal_Unicode
signed char sal_Int8