1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scripting.hxx"
26 #include "stringresource.hxx"
27 #include <com/sun/star/io/XTextInputStream.hpp>
28 #include <com/sun/star/io/XTextOutputStream.hpp>
29 #include <com/sun/star/io/XActiveDataSink.hpp>
30 #include <com/sun/star/io/XActiveDataSource.hpp>
31 #include <com/sun/star/io/XStream.hpp>
32 #include <com/sun/star/io/XSeekable.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
35 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
36 #include <cppuhelper/implementationentry.hxx>
37 #endif
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40
41
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/strbuf.hxx>
44 #include <tools/urlobj.hxx>
45
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::ucb;
50 using namespace ::com::sun::star::util;
51 using namespace ::com::sun::star::embed;
52 using namespace ::com::sun::star::container;
53
54
55 //.........................................................................
56 namespace stringresource
57 {
58 //.........................................................................
59
60 // =============================================================================
61 // mutex
62 // =============================================================================
63
getMutex()64 ::osl::Mutex& getMutex()
65 {
66 static ::osl::Mutex* s_pMutex = 0;
67 if ( !s_pMutex )
68 {
69 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
70 if ( !s_pMutex )
71 {
72 static ::osl::Mutex s_aMutex;
73 s_pMutex = &s_aMutex;
74 }
75 }
76 return *s_pMutex;
77 }
78
79
80 // =============================================================================
81 // StringResourceImpl
82 // =============================================================================
83
84 // component operations
getSupportedServiceNames_StringResourceImpl()85 static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceImpl()
86 {
87 Sequence< ::rtl::OUString > names(1);
88 names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResource") );
89 return names;
90 }
91
getImplementationName_StringResourceImpl()92 static ::rtl::OUString getImplementationName_StringResourceImpl()
93 {
94 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResource") );
95 }
96
create_StringResourceImpl(Reference<XComponentContext> const & xContext)97 static Reference< XInterface > SAL_CALL create_StringResourceImpl(
98 Reference< XComponentContext > const & xContext )
99 SAL_THROW( () )
100 {
101 return static_cast< ::cppu::OWeakObject * >( new StringResourcePersistenceImpl( xContext ) );
102 }
103
104
105 // =============================================================================
106
StringResourceImpl(const Reference<XComponentContext> & rxContext)107 StringResourceImpl::StringResourceImpl( const Reference< XComponentContext >& rxContext )
108 : m_xContext( rxContext )
109 , m_pCurrentLocaleItem( NULL )
110 , m_pDefaultLocaleItem( NULL )
111 , m_bDefaultModified( false )
112 , m_aListenerContainer( getMutex() )
113 , m_bModified( false )
114 , m_bReadOnly( false )
115 , m_nNextUniqueNumericId( UNIQUE_NUMBER_NEEDS_INITIALISATION )
116 {
117 }
118
119 // =============================================================================
120
~StringResourceImpl()121 StringResourceImpl::~StringResourceImpl()
122 {
123 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
124 {
125 LocaleItem* pLocaleItem = *it;
126 delete pLocaleItem;
127 }
128
129 for( LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin(); it != m_aDeletedLocaleItemVector.end(); it++ )
130 {
131 LocaleItem* pLocaleItem = *it;
132 delete pLocaleItem;
133 }
134 }
135
136
137 // =============================================================================
138 // XServiceInfo
139
getImplementationName()140 ::rtl::OUString StringResourceImpl::getImplementationName( )
141 {
142 return getImplementationName_StringResourceImpl();
143 }
144
supportsService(const::rtl::OUString & rServiceName)145 sal_Bool StringResourceImpl::supportsService( const ::rtl::OUString& rServiceName )
146 {
147 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
148 const ::rtl::OUString* pNames = aNames.getConstArray();
149 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
150 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
151 ;
152
153 return pNames != pEnd;
154 }
155
getSupportedServiceNames()156 Sequence< ::rtl::OUString > StringResourceImpl::getSupportedServiceNames( )
157 {
158 return getSupportedServiceNames_StringResourceImpl();
159 }
160
161
162 // =============================================================================
163 // XModifyBroadcaster
164
addModifyListener(const Reference<XModifyListener> & aListener)165 void StringResourceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
166 {
167 if( !aListener.is() )
168 throw RuntimeException();
169
170 ::osl::MutexGuard aGuard( getMutex() );
171 Reference< XInterface > xIface( aListener, UNO_QUERY );
172 m_aListenerContainer.addInterface( xIface );
173 }
174
removeModifyListener(const Reference<XModifyListener> & aListener)175 void StringResourceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
176 {
177 if( !aListener.is() )
178 throw RuntimeException();
179
180 ::osl::MutexGuard aGuard( getMutex() );
181 Reference< XInterface > xIface( aListener, UNO_QUERY );
182 m_aListenerContainer.removeInterface( xIface );
183 }
184
185
186 // =============================================================================
187 // XStringResourceResolver
188
implResolveString(const::rtl::OUString & ResourceID,LocaleItem * pLocaleItem)189 ::rtl::OUString StringResourceImpl::implResolveString
190 ( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem )
191 {
192 ::rtl::OUString aRetStr;
193 bool bSuccess = false;
194 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
195 {
196 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
197 if( !( it == pLocaleItem->m_aIdToStringMap.end() ) )
198 {
199 aRetStr = (*it).second;
200 bSuccess = true;
201 }
202 }
203 if( !bSuccess )
204 {
205 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: No entry for ResourceID: " );
206 errorMsg.concat( ResourceID );
207 throw ::com::sun::star::resource::MissingResourceException( errorMsg, Reference< XInterface >() );
208 }
209 return aRetStr;
210 }
211
resolveString(const::rtl::OUString & ResourceID)212 ::rtl::OUString StringResourceImpl::resolveString( const ::rtl::OUString& ResourceID )
213 {
214 ::osl::MutexGuard aGuard( getMutex() );
215 return implResolveString( ResourceID, m_pCurrentLocaleItem );
216 }
217
resolveStringForLocale(const::rtl::OUString & ResourceID,const Locale & locale)218 ::rtl::OUString StringResourceImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
219 {
220 ::osl::MutexGuard aGuard( getMutex() );
221 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
222 return implResolveString( ResourceID, pLocaleItem );
223 }
224
implHasEntryForId(const::rtl::OUString & ResourceID,LocaleItem * pLocaleItem)225 sal_Bool StringResourceImpl::implHasEntryForId( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem )
226 {
227 bool bSuccess = false;
228 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
229 {
230 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
231 if( !( it == pLocaleItem->m_aIdToStringMap.end() ) )
232 bSuccess = true;
233 }
234 return bSuccess;
235 }
236
hasEntryForId(const::rtl::OUString & ResourceID)237 sal_Bool StringResourceImpl::hasEntryForId( const ::rtl::OUString& ResourceID )
238 {
239 ::osl::MutexGuard aGuard( getMutex() );
240 return implHasEntryForId( ResourceID, m_pCurrentLocaleItem );
241 }
242
hasEntryForIdAndLocale(const::rtl::OUString & ResourceID,const Locale & locale)243 sal_Bool StringResourceImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID,
244 const Locale& locale )
245 {
246 ::osl::MutexGuard aGuard( getMutex() );
247 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
248 return implHasEntryForId( ResourceID, pLocaleItem );
249 }
250
implGetResourceIDs(LocaleItem * pLocaleItem)251 Sequence< ::rtl::OUString > StringResourceImpl::implGetResourceIDs( LocaleItem* pLocaleItem )
252 {
253 Sequence< ::rtl::OUString > aIDSeq( 0 );
254 if( pLocaleItem && loadLocale( pLocaleItem ) )
255 {
256 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
257 sal_Int32 nResourceIDCount = rHashMap.size();
258 aIDSeq.realloc( nResourceIDCount );
259 ::rtl::OUString* pStrings = aIDSeq.getArray();
260
261 IdToStringMap::const_iterator it;
262 int iTarget = 0;
263 for( it = rHashMap.begin(); it != rHashMap.end(); it++ )
264 {
265 ::rtl::OUString aStr = (*it).first;
266 pStrings[iTarget] = aStr;
267 iTarget++;
268 }
269 }
270 return aIDSeq;
271 }
272
getResourceIDsForLocale(const Locale & locale)273 Sequence< ::rtl::OUString > StringResourceImpl::getResourceIDsForLocale
274 ( const Locale& locale )
275 {
276 ::osl::MutexGuard aGuard( getMutex() );
277 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
278 return implGetResourceIDs( pLocaleItem );
279 }
280
getResourceIDs()281 Sequence< ::rtl::OUString > StringResourceImpl::getResourceIDs( )
282 {
283 ::osl::MutexGuard aGuard( getMutex() );
284 return implGetResourceIDs( m_pCurrentLocaleItem );
285 }
286
getCurrentLocale()287 Locale StringResourceImpl::getCurrentLocale()
288 {
289 ::osl::MutexGuard aGuard( getMutex() );
290
291 Locale aRetLocale;
292 if( m_pCurrentLocaleItem != NULL )
293 aRetLocale = m_pCurrentLocaleItem->m_locale;
294 return aRetLocale;
295 }
296
getDefaultLocale()297 Locale StringResourceImpl::getDefaultLocale( )
298 {
299 ::osl::MutexGuard aGuard( getMutex() );
300
301 Locale aRetLocale;
302 if( m_pDefaultLocaleItem != NULL )
303 aRetLocale = m_pDefaultLocaleItem->m_locale;
304 return aRetLocale;
305 }
306
getLocales()307 Sequence< Locale > StringResourceImpl::getLocales( )
308 {
309 ::osl::MutexGuard aGuard( getMutex() );
310
311 sal_Int32 nSize = m_aLocaleItemVector.size();
312 Sequence< Locale > aLocalSeq( nSize );
313 Locale* pLocales = aLocalSeq.getArray();
314 int iTarget = 0;
315 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
316 {
317 LocaleItem* pLocaleItem = *it;
318 pLocales[iTarget] = pLocaleItem->m_locale;
319 iTarget++;
320 }
321 return aLocalSeq;
322 }
323
324
325 // =============================================================================
326 // XStringResourceManager
327
implCheckReadOnly(const sal_Char * pExceptionMsg)328 void StringResourceImpl::implCheckReadOnly( const sal_Char* pExceptionMsg )
329 {
330 if( m_bReadOnly )
331 {
332 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( pExceptionMsg );
333 throw NoSupportException( errorMsg, Reference< XInterface >() );
334 }
335 }
336
isReadOnly()337 sal_Bool StringResourceImpl::isReadOnly()
338 {
339 return m_bReadOnly;
340 }
341
implSetCurrentLocale(const Locale & locale,sal_Bool FindClosestMatch,sal_Bool bUseDefaultIfNoMatch)342 void StringResourceImpl::implSetCurrentLocale( const Locale& locale,
343 sal_Bool FindClosestMatch, sal_Bool bUseDefaultIfNoMatch )
344 {
345 ::osl::MutexGuard aGuard( getMutex() );
346
347 LocaleItem* pLocaleItem = NULL;
348 if( FindClosestMatch )
349 pLocaleItem = getClosestMatchItemForLocale( locale );
350 else
351 pLocaleItem = getItemForLocale( locale, true );
352
353 if( pLocaleItem == NULL && bUseDefaultIfNoMatch )
354 pLocaleItem = m_pDefaultLocaleItem;
355
356 if( pLocaleItem != NULL )
357 {
358 loadLocale( pLocaleItem );
359 m_pCurrentLocaleItem = pLocaleItem;
360
361 // Only notify without modifying
362 implNotifyListeners();
363 }
364 }
365
setCurrentLocale(const Locale & locale,sal_Bool FindClosestMatch)366 void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
367 {
368 sal_Bool bUseDefaultIfNoMatch = false;
369 implSetCurrentLocale( locale, FindClosestMatch, bUseDefaultIfNoMatch );
370 }
371
setDefaultLocale(const Locale & locale)372 void StringResourceImpl::setDefaultLocale( const Locale& locale )
373 {
374 ::osl::MutexGuard aGuard( getMutex() );
375 implCheckReadOnly( "StringResourceImpl::setDefaultLocale(): Read only" );
376
377 LocaleItem* pLocaleItem = getItemForLocale( locale, true );
378 if( pLocaleItem && pLocaleItem != m_pDefaultLocaleItem )
379 {
380 if( m_pDefaultLocaleItem )
381 {
382 LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale );
383 m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem );
384 }
385
386 m_pDefaultLocaleItem = pLocaleItem;
387 m_bDefaultModified = true;
388 implModified();
389 }
390 }
391
implSetString(const::rtl::OUString & ResourceID,const::rtl::OUString & Str,LocaleItem * pLocaleItem)392 void StringResourceImpl::implSetString( const ::rtl::OUString& ResourceID,
393 const ::rtl::OUString& Str, LocaleItem* pLocaleItem )
394 {
395 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
396 {
397 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
398
399 IdToStringMap::iterator it = rHashMap.find( ResourceID );
400 bool bNew = ( it == rHashMap.end() );
401 if( bNew )
402 {
403 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
404 rIndexMap[ ResourceID ] = pLocaleItem->m_nNextIndex++;
405 implScanIdForNumber( ResourceID );
406 }
407 rHashMap[ ResourceID ] = Str;
408 pLocaleItem->m_bModified = true;
409 implModified();
410 }
411 }
412
setString(const::rtl::OUString & ResourceID,const::rtl::OUString & Str)413 void StringResourceImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str )
414 {
415 ::osl::MutexGuard aGuard( getMutex() );
416 implCheckReadOnly( "StringResourceImpl::setString(): Read only" );
417 implSetString( ResourceID, Str, m_pCurrentLocaleItem );
418 }
419
setStringForLocale(const::rtl::OUString & ResourceID,const::rtl::OUString & Str,const Locale & locale)420 void StringResourceImpl::setStringForLocale
421 ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale )
422 {
423 ::osl::MutexGuard aGuard( getMutex() );
424 implCheckReadOnly( "StringResourceImpl::setStringForLocale(): Read only" );
425 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
426 implSetString( ResourceID, Str, pLocaleItem );
427 }
428
implRemoveId(const::rtl::OUString & ResourceID,LocaleItem * pLocaleItem)429 void StringResourceImpl::implRemoveId( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem )
430 {
431 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
432 {
433 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
434 IdToStringMap::iterator it = rHashMap.find( ResourceID );
435 if( it == rHashMap.end() )
436 {
437 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: No entries for ResourceID: " );
438 errorMsg.concat( ResourceID );
439 throw ::com::sun::star::resource::MissingResourceException( errorMsg, Reference< XInterface >() );
440 }
441 rHashMap.erase( it );
442 pLocaleItem->m_bModified = true;
443 implModified();
444 }
445 }
446
removeId(const::rtl::OUString & ResourceID)447 void StringResourceImpl::removeId( const ::rtl::OUString& ResourceID )
448 {
449 ::osl::MutexGuard aGuard( getMutex() );
450 implCheckReadOnly( "StringResourceImpl::removeId(): Read only" );
451 implRemoveId( ResourceID, m_pCurrentLocaleItem );
452 }
453
removeIdForLocale(const::rtl::OUString & ResourceID,const Locale & locale)454 void StringResourceImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
455 {
456 ::osl::MutexGuard aGuard( getMutex() );
457 implCheckReadOnly( "StringResourceImpl::removeIdForLocale(): Read only" );
458 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
459 implRemoveId( ResourceID, pLocaleItem );
460 }
461
newLocale(const Locale & locale)462 void StringResourceImpl::newLocale( const Locale& locale )
463 {
464 ::osl::MutexGuard aGuard( getMutex() );
465 implCheckReadOnly( "StringResourceImpl::newLocale(): Read only" );
466
467 if( getItemForLocale( locale, false ) != NULL )
468 {
469 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: locale already exists" );
470 throw ElementExistException( errorMsg, Reference< XInterface >() );
471 }
472
473 // TODO?: Check if locale is valid? How?
474 bool bValid = true;
475 if( bValid )
476 {
477 LocaleItem* pLocaleItem = new LocaleItem( locale );
478 m_aLocaleItemVector.push_back( pLocaleItem );
479 pLocaleItem->m_bModified = true;
480
481 // Copy strings from default locale
482 LocaleItem* pCopyFromItem = m_pDefaultLocaleItem;
483 if( pCopyFromItem == NULL )
484 pCopyFromItem = m_pCurrentLocaleItem;
485 if( pCopyFromItem != NULL && loadLocale( pCopyFromItem ) )
486 {
487 const IdToStringMap& rSourceMap = pCopyFromItem->m_aIdToStringMap;
488 IdToStringMap& rTargetMap = pLocaleItem->m_aIdToStringMap;
489 IdToStringMap::const_iterator it;
490 for( it = rSourceMap.begin(); it != rSourceMap.end(); it++ )
491 {
492 ::rtl::OUString aId = (*it).first;
493 ::rtl::OUString aStr = (*it).second;
494 rTargetMap[ aId ] = aStr;
495 }
496
497 const IdToIndexMap& rSourceIndexMap = pCopyFromItem->m_aIdToIndexMap;
498 IdToIndexMap& rTargetIndexMap = pLocaleItem->m_aIdToIndexMap;
499 IdToIndexMap::const_iterator it_index;
500 for( it_index = rSourceIndexMap.begin(); it_index != rSourceIndexMap.end(); it_index++ )
501 {
502 ::rtl::OUString aId = (*it_index).first;
503 sal_Int32 nIndex = (*it_index).second;
504 rTargetIndexMap[ aId ] = nIndex;
505 }
506 pLocaleItem->m_nNextIndex = pCopyFromItem->m_nNextIndex;
507 }
508
509 if( m_pCurrentLocaleItem == NULL )
510 m_pCurrentLocaleItem = pLocaleItem;
511
512 if( m_pDefaultLocaleItem == NULL )
513 {
514 m_pDefaultLocaleItem = pLocaleItem;
515 m_bDefaultModified = true;
516 }
517
518 implModified();
519 }
520 else
521 {
522 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: Invalid locale" );
523 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
524 }
525 }
526
removeLocale(const Locale & locale)527 void StringResourceImpl::removeLocale( const Locale& locale )
528 {
529 ::osl::MutexGuard aGuard( getMutex() );
530 implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" );
531
532 LocaleItem* pRemoveItem = getItemForLocale( locale, true );
533 if( pRemoveItem )
534 {
535 // Last locale?
536 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
537 if( nLocaleCount > 1 )
538 {
539 LocaleItem* pFallbackItem = NULL;
540 if( m_pCurrentLocaleItem == pRemoveItem ||
541 m_pDefaultLocaleItem == pRemoveItem )
542 {
543 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
544 {
545 LocaleItem* pLocaleItem = *it;
546 if( pLocaleItem != pRemoveItem )
547 {
548 pFallbackItem = pLocaleItem;
549 break;
550 }
551 }
552 if( m_pCurrentLocaleItem == pRemoveItem )
553 {
554 sal_Bool FindClosestMatch = false;
555 setCurrentLocale( pFallbackItem->m_locale, FindClosestMatch );
556 }
557 if( m_pDefaultLocaleItem == pRemoveItem )
558 {
559 setDefaultLocale( pFallbackItem->m_locale );
560 }
561 }
562 }
563 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
564 {
565 LocaleItem* pLocaleItem = *it;
566 if( pLocaleItem == pRemoveItem )
567 {
568 // Remember locale item to delete file while storing
569 m_aDeletedLocaleItemVector.push_back( pLocaleItem );
570
571 // Last locale?
572 if( nLocaleCount == 1 )
573 {
574 m_nNextUniqueNumericId = 0;
575 if( m_pDefaultLocaleItem )
576 {
577 LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale );
578 m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem );
579 }
580 m_pCurrentLocaleItem = NULL;
581 m_pDefaultLocaleItem = NULL;
582 }
583
584 m_aLocaleItemVector.erase( it );
585
586 implModified();
587 break;
588 }
589 }
590 }
591 }
592
implScanIdForNumber(const::rtl::OUString & ResourceID)593 void StringResourceImpl::implScanIdForNumber( const ::rtl::OUString& ResourceID )
594 {
595 const sal_Unicode* pSrc = ResourceID.getStr();
596 sal_Int32 nLen = ResourceID.getLength();
597
598 sal_Int32 nNumber = 0;
599 for( sal_Int32 i = 0 ; i < nLen ; i++ )
600 {
601 sal_Unicode c = pSrc[i];
602 if( c >= '0' && c <= '9' )
603 {
604 sal_uInt16 nDigitVal = c - '0';
605 nNumber = 10*nNumber + nDigitVal;
606 }
607 else
608 break;
609 }
610
611 if( m_nNextUniqueNumericId < nNumber + 1 )
612 m_nNextUniqueNumericId = nNumber + 1;
613 }
614
getUniqueNumericId()615 sal_Int32 StringResourceImpl::getUniqueNumericId( )
616 {
617 if( m_nNextUniqueNumericId == UNIQUE_NUMBER_NEEDS_INITIALISATION )
618 {
619 implLoadAllLocales();
620 m_nNextUniqueNumericId = 0;
621 }
622
623 if( m_nNextUniqueNumericId < UNIQUE_NUMBER_NEEDS_INITIALISATION )
624 {
625 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "getUniqueNumericId: Extended sal_Int32 range" );
626 throw NoSupportException( errorMsg, Reference< XInterface >() );
627 }
628 return m_nNextUniqueNumericId;
629 }
630
631
632 // =============================================================================
633 // Private helper methods
634
getItemForLocale(const Locale & locale,sal_Bool bException)635 LocaleItem* StringResourceImpl::getItemForLocale
636 ( const Locale& locale, sal_Bool bException )
637 {
638 LocaleItem* pRetItem = NULL;
639
640 // Search for locale
641 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
642 {
643 LocaleItem* pLocaleItem = *it;
644 if( pLocaleItem )
645 {
646 Locale& cmp_locale = pLocaleItem->m_locale;
647 if( cmp_locale.Language == locale.Language &&
648 cmp_locale.Country == locale.Country &&
649 cmp_locale.Variant == locale.Variant )
650 {
651 pRetItem = pLocaleItem;
652 break;
653 }
654 }
655 }
656
657 if( pRetItem == NULL && bException )
658 {
659 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: Invalid locale" );
660 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
661 }
662 return pRetItem;
663 }
664
665 // Returns the LocalItem for a given locale, if it exists, otherwise NULL
666 // This method performs a closest match search, at least the language must match
getClosestMatchItemForLocale(const Locale & locale)667 LocaleItem* StringResourceImpl::getClosestMatchItemForLocale( const Locale& locale )
668 {
669 LocaleItem* pRetItem = NULL;
670
671 // Search for locale
672 for( sal_Int32 iPass = 0 ; iPass <= 2 ; ++iPass )
673 {
674 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
675 {
676 LocaleItem* pLocaleItem = *it;
677 if( pLocaleItem )
678 {
679 Locale& cmp_locale = pLocaleItem->m_locale;
680 if( cmp_locale.Language == locale.Language &&
681 (iPass > 1 || cmp_locale.Country == locale.Country) &&
682 (iPass > 0 || cmp_locale.Variant == locale.Variant) )
683 {
684 pRetItem = pLocaleItem;
685 break;
686 }
687 }
688 }
689 if( pRetItem )
690 break;
691 }
692
693 return pRetItem;
694 }
695
implModified(void)696 void StringResourceImpl::implModified( void )
697 {
698 m_bModified = true;
699 implNotifyListeners();
700 }
701
implNotifyListeners(void)702 void StringResourceImpl::implNotifyListeners( void )
703 {
704 EventObject aEvent;
705 aEvent.Source = static_cast< XInterface* >( (OWeakObject*)this );
706
707 ::cppu::OInterfaceIteratorHelper it( m_aListenerContainer );
708 while( it.hasMoreElements() )
709 {
710 Reference< XInterface > xIface = it.next();
711 Reference< XModifyListener > xListener( xIface, UNO_QUERY );
712 try
713 {
714 xListener->modified( aEvent );
715 }
716 catch(RuntimeException&)
717 {
718 it.remove();
719 }
720 }
721 }
722
723
724 // =============================================================================
725 // Loading
726
loadLocale(LocaleItem * pLocaleItem)727 bool StringResourceImpl::loadLocale( LocaleItem* pLocaleItem )
728 {
729 // Base implementation has nothing to load
730 (void)pLocaleItem;
731 return true;
732 }
733
implLoadAllLocales(void)734 void StringResourceImpl::implLoadAllLocales( void )
735 {
736 // Base implementation has nothing to load
737 }
738
739
getMultiComponentFactory(void)740 Reference< XMultiComponentFactory > StringResourceImpl::getMultiComponentFactory( void )
741 {
742 ::osl::MutexGuard aGuard( getMutex() );
743
744 if( !m_xMCF.is() )
745 {
746 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
747 if( !xSMgr.is() )
748 {
749 throw RuntimeException(
750 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringResourceImpl::getMultiComponentFactory: Couldn't instantiate MultiComponentFactory" ) ),
751 Reference< XInterface >() );
752 }
753 m_xMCF = xSMgr;
754 }
755 return m_xMCF;
756 }
757
758
759 // =============================================================================
760 // StringResourcePersistenceImpl
761 // =============================================================================
762
StringResourcePersistenceImpl(const Reference<XComponentContext> & rxContext)763 StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext )
764 : StringResourcePersistenceImpl_BASE( rxContext )
765 {
766 }
767
768 // -----------------------------------------------------------------------------
769
~StringResourcePersistenceImpl()770 StringResourcePersistenceImpl::~StringResourcePersistenceImpl()
771 {
772 }
773
774 // -----------------------------------------------------------------------------
775 // XServiceInfo
776 // -----------------------------------------------------------------------------
777
getImplementationName()778 ::rtl::OUString StringResourcePersistenceImpl::getImplementationName( )
779 {
780 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM
781 ( "com.sun.star.comp.scripting.StringResourceWithLocation") );
782 }
783
784 // -----------------------------------------------------------------------------
785
supportsService(const::rtl::OUString & rServiceName)786 sal_Bool StringResourcePersistenceImpl::supportsService( const ::rtl::OUString& rServiceName )
787 {
788 return StringResourceImpl::supportsService( rServiceName );
789 }
790
791 // -----------------------------------------------------------------------------
792
getSupportedServiceNames()793 Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getSupportedServiceNames( )
794 {
795 return StringResourceImpl::getSupportedServiceNames();
796 }
797
798 // -----------------------------------------------------------------------------
799 // XInitialization base functionality for derived classes
800 // -----------------------------------------------------------------------------
801
802 static ::rtl::OUString aNameBaseDefaultStr = ::rtl::OUString::createFromAscii( "strings" );
803
implInitializeCommonParameters(const Sequence<Any> & aArguments)804 void StringResourcePersistenceImpl::implInitializeCommonParameters
805 ( const Sequence< Any >& aArguments )
806 {
807 bool bReadOnlyOk = (aArguments[1] >>= m_bReadOnly);
808 if( !bReadOnlyOk )
809 {
810 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected ReadOnly flag" );
811 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 1 );
812 }
813
814 com::sun::star::lang::Locale aCurrentLocale;
815 bool bLocaleOk = (aArguments[2] >>= aCurrentLocale);
816 if( !bLocaleOk )
817 {
818 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected Locale" );
819 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 2 );
820 }
821
822 bool bNameBaseOk = (aArguments[3] >>= m_aNameBase);
823 if( !bNameBaseOk )
824 {
825 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected NameBase string" );
826 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 3 );
827 }
828 if( m_aNameBase.getLength() == 0 )
829 m_aNameBase = aNameBaseDefaultStr;
830
831 bool bCommentOk = (aArguments[4] >>= m_aComment);
832 if( !bCommentOk )
833 {
834 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected Comment string" );
835 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 4 );
836 }
837
838 implScanLocales();
839
840 sal_Bool FindClosestMatch = true;
841 sal_Bool bUseDefaultIfNoMatch = true;
842 implSetCurrentLocale( aCurrentLocale, FindClosestMatch, bUseDefaultIfNoMatch );
843 }
844
845 // -----------------------------------------------------------------------------
846 // Forwarding calls to base class
847
848 // XModifyBroadcaster
addModifyListener(const Reference<XModifyListener> & aListener)849 void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
850 {
851 StringResourceImpl::addModifyListener( aListener );
852 }
removeModifyListener(const Reference<XModifyListener> & aListener)853 void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
854 {
855 StringResourceImpl::removeModifyListener( aListener );
856 }
857
858 // XStringResourceResolver
resolveString(const::rtl::OUString & ResourceID)859 ::rtl::OUString StringResourcePersistenceImpl::resolveString( const ::rtl::OUString& ResourceID )
860 {
861 return StringResourceImpl::resolveString( ResourceID ) ;
862 }
resolveStringForLocale(const::rtl::OUString & ResourceID,const Locale & locale)863 ::rtl::OUString StringResourcePersistenceImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
864 {
865 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
866 }
hasEntryForId(const::rtl::OUString & ResourceID)867 sal_Bool StringResourcePersistenceImpl::hasEntryForId( const ::rtl::OUString& ResourceID )
868 {
869 return StringResourceImpl::hasEntryForId( ResourceID ) ;
870 }
hasEntryForIdAndLocale(const::rtl::OUString & ResourceID,const Locale & locale)871 sal_Bool StringResourcePersistenceImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID,
872 const Locale& locale )
873 {
874 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
875 }
getCurrentLocale()876 Locale StringResourcePersistenceImpl::getCurrentLocale()
877 {
878 return StringResourceImpl::getCurrentLocale();
879 }
getDefaultLocale()880 Locale StringResourcePersistenceImpl::getDefaultLocale( )
881 {
882 return StringResourceImpl::getDefaultLocale();
883 }
getLocales()884 Sequence< Locale > StringResourcePersistenceImpl::getLocales( )
885 {
886 return StringResourceImpl::getLocales();
887 }
888
889 // XStringResourceManager
isReadOnly()890 sal_Bool StringResourcePersistenceImpl::isReadOnly()
891 {
892 return StringResourceImpl::isReadOnly();
893 }
setCurrentLocale(const Locale & locale,sal_Bool FindClosestMatch)894 void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
895 {
896 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
897 }
setDefaultLocale(const Locale & locale)898 void StringResourcePersistenceImpl::setDefaultLocale( const Locale& locale )
899 {
900 StringResourceImpl::setDefaultLocale( locale );
901 }
getResourceIDs()902 Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getResourceIDs( )
903 {
904 return StringResourceImpl::getResourceIDs();
905 }
setString(const::rtl::OUString & ResourceID,const::rtl::OUString & Str)906 void StringResourcePersistenceImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str )
907 {
908 StringResourceImpl::setString( ResourceID, Str );
909 }
setStringForLocale(const::rtl::OUString & ResourceID,const::rtl::OUString & Str,const Locale & locale)910 void StringResourcePersistenceImpl::setStringForLocale
911 ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale )
912 {
913 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
914 }
getResourceIDsForLocale(const Locale & locale)915 Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getResourceIDsForLocale
916 ( const Locale& locale )
917 {
918 return StringResourceImpl::getResourceIDsForLocale( locale );
919 }
removeId(const::rtl::OUString & ResourceID)920 void StringResourcePersistenceImpl::removeId( const ::rtl::OUString& ResourceID )
921 {
922 StringResourceImpl::removeId( ResourceID );
923 }
removeIdForLocale(const::rtl::OUString & ResourceID,const Locale & locale)924 void StringResourcePersistenceImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
925 {
926 StringResourceImpl::removeIdForLocale( ResourceID, locale );
927 }
newLocale(const Locale & locale)928 void StringResourcePersistenceImpl::newLocale( const Locale& locale )
929 {
930 StringResourceImpl::newLocale( locale );
931 }
removeLocale(const Locale & locale)932 void StringResourcePersistenceImpl::removeLocale( const Locale& locale )
933 {
934 StringResourceImpl::removeLocale( locale );
935 }
getUniqueNumericId()936 sal_Int32 StringResourcePersistenceImpl::getUniqueNumericId( )
937 {
938 return StringResourceImpl::getUniqueNumericId();
939 }
940
941 // -----------------------------------------------------------------------------
942 // XStringResourcePersistence
943
store()944 void StringResourcePersistenceImpl::store()
945 {
946 }
947
isModified()948 sal_Bool StringResourcePersistenceImpl::isModified( )
949 {
950 ::osl::MutexGuard aGuard( getMutex() );
951
952 return m_bModified;
953 }
954
setComment(const::rtl::OUString & Comment)955 void StringResourcePersistenceImpl::setComment( const ::rtl::OUString& Comment )
956 {
957 m_aComment = Comment;
958 }
959
storeToStorage(const Reference<XStorage> & Storage,const::rtl::OUString & NameBase,const::rtl::OUString & Comment)960 void StringResourcePersistenceImpl::storeToStorage( const Reference< XStorage >& Storage,
961 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment )
962 {
963 ::osl::MutexGuard aGuard( getMutex() );
964
965 bool bUsedForStore = false;
966 bool bStoreAll = true;
967 implStoreAtStorage( NameBase, Comment, Storage, bUsedForStore, bStoreAll );
968 }
969
implStoreAtStorage(const::rtl::OUString & aNameBase,const::rtl::OUString & aComment,const Reference<::com::sun::star::embed::XStorage> & Storage,bool bUsedForStore,bool bStoreAll)970 void StringResourcePersistenceImpl::implStoreAtStorage
971 (
972 const ::rtl::OUString& aNameBase,
973 const ::rtl::OUString& aComment,
974 const Reference< ::com::sun::star::embed::XStorage >& Storage,
975 bool bUsedForStore,
976 bool bStoreAll
977 )
978 {
979 // Delete files for deleted locales
980 if( bUsedForStore )
981 {
982 while( m_aDeletedLocaleItemVector.size() > 0 )
983 {
984 LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin();
985 LocaleItem* pLocaleItem = *it;
986 if( pLocaleItem != NULL )
987 {
988 ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
989 aStreamName += ::rtl::OUString::createFromAscii( ".properties" );
990
991 try
992 {
993 Storage->removeElement( aStreamName );
994 }
995 catch( Exception& )
996 {}
997
998 m_aDeletedLocaleItemVector.erase( it );
999 delete pLocaleItem;
1000 }
1001 }
1002 }
1003
1004 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
1005 {
1006 LocaleItem* pLocaleItem = *it;
1007 if( pLocaleItem != NULL && (bStoreAll || pLocaleItem->m_bModified) &&
1008 loadLocale( pLocaleItem ) )
1009 {
1010 ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1011 aStreamName += ::rtl::OUString::createFromAscii( ".properties" );
1012
1013 Reference< io::XStream > xElementStream =
1014 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
1015
1016 ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "MediaType" );
1017 ::rtl::OUString aMime = ::rtl::OUString::createFromAscii( "text/plain" );
1018
1019 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
1020 OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!\n" );
1021 if ( xProps.is() )
1022 {
1023 xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
1024
1025 aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1026 xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) );
1027 }
1028
1029 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
1030 if( xOutputStream.is() )
1031 implWritePropertiesFile( pLocaleItem, xOutputStream, aComment );
1032 xOutputStream->closeOutput();
1033
1034 if( bUsedForStore )
1035 pLocaleItem->m_bModified = false;
1036 }
1037 }
1038
1039 // Delete files for changed defaults
1040 if( bUsedForStore )
1041 {
1042 for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin();
1043 it != m_aChangedDefaultLocaleVector.end(); it++ )
1044 {
1045 LocaleItem* pLocaleItem = *it;
1046 if( pLocaleItem != NULL )
1047 {
1048 ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
1049 aStreamName += ::rtl::OUString::createFromAscii( ".default" );
1050
1051 try
1052 {
1053 Storage->removeElement( aStreamName );
1054 }
1055 catch( Exception& )
1056 {}
1057
1058 delete pLocaleItem;
1059 }
1060 }
1061 m_aChangedDefaultLocaleVector.clear();
1062 }
1063
1064 // Default locale
1065 if( m_pDefaultLocaleItem != NULL && (bStoreAll || m_bDefaultModified) )
1066 {
1067 ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( m_pDefaultLocaleItem, aNameBase );
1068 aStreamName += ::rtl::OUString::createFromAscii( ".default" );
1069
1070 Reference< io::XStream > xElementStream =
1071 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
1072
1073 ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "MediaType" );
1074 ::rtl::OUString aMime = ::rtl::OUString::createFromAscii( "text/plain" );
1075
1076 // Only create stream without content
1077 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
1078 xOutputStream->closeOutput();
1079
1080 if( bUsedForStore )
1081 m_bDefaultModified = false;
1082 }
1083 }
1084
storeToURL(const::rtl::OUString & URL,const::rtl::OUString & NameBase,const::rtl::OUString & Comment,const Reference<::com::sun::star::task::XInteractionHandler> & Handler)1085 void StringResourcePersistenceImpl::storeToURL( const ::rtl::OUString& URL,
1086 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment,
1087 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
1088 {
1089 ::osl::MutexGuard aGuard( getMutex() );
1090
1091 bool bUsedForStore = false;
1092 bool bStoreAll = true;
1093
1094 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1095 Reference< ucb::XSimpleFileAccess > xFileAccess;
1096 xFileAccess = Reference< ucb::XSimpleFileAccess >( xMCF->createInstanceWithContext
1097 ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
1098 m_xContext ), UNO_QUERY );
1099 if( xFileAccess.is() && Handler.is() )
1100 xFileAccess->setInteractionHandler( Handler );
1101
1102 implStoreAtLocation( URL, NameBase, Comment, xFileAccess, bUsedForStore, bStoreAll );
1103 }
1104
implKillRemovedLocaleFiles(const::rtl::OUString & Location,const::rtl::OUString & aNameBase,const::com::sun::star::uno::Reference<::com::sun::star::ucb::XSimpleFileAccess> & xFileAccess)1105 void StringResourcePersistenceImpl::implKillRemovedLocaleFiles
1106 (
1107 const ::rtl::OUString& Location,
1108 const ::rtl::OUString& aNameBase,
1109 const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xFileAccess
1110 )
1111 {
1112 // Delete files for deleted locales
1113 while( m_aDeletedLocaleItemVector.size() > 0 )
1114 {
1115 LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin();
1116 LocaleItem* pLocaleItem = *it;
1117 if( pLocaleItem != NULL )
1118 {
1119 ::rtl::OUString aCompleteFileName =
1120 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location );
1121 if( xFileAccess->exists( aCompleteFileName ) )
1122 xFileAccess->kill( aCompleteFileName );
1123
1124 m_aDeletedLocaleItemVector.erase( it );
1125 delete pLocaleItem;
1126 }
1127 }
1128 }
1129
implKillChangedDefaultFiles(const::rtl::OUString & Location,const::rtl::OUString & aNameBase,const::com::sun::star::uno::Reference<::com::sun::star::ucb::XSimpleFileAccess> & xFileAccess)1130 void StringResourcePersistenceImpl::implKillChangedDefaultFiles
1131 (
1132 const ::rtl::OUString& Location,
1133 const ::rtl::OUString& aNameBase,
1134 const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xFileAccess
1135 )
1136 {
1137 // Delete files for changed defaults
1138 for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin();
1139 it != m_aChangedDefaultLocaleVector.end(); it++ )
1140 {
1141 LocaleItem* pLocaleItem = *it;
1142 if( pLocaleItem != NULL )
1143 {
1144 ::rtl::OUString aCompleteFileName =
1145 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location, true );
1146 if( xFileAccess->exists( aCompleteFileName ) )
1147 xFileAccess->kill( aCompleteFileName );
1148
1149 delete pLocaleItem;
1150 }
1151 }
1152 m_aChangedDefaultLocaleVector.clear();
1153 }
1154
implStoreAtLocation(const::rtl::OUString & Location,const::rtl::OUString & aNameBase,const::rtl::OUString & aComment,const Reference<ucb::XSimpleFileAccess> & xFileAccess,bool bUsedForStore,bool bStoreAll,bool bKillAll)1155 void StringResourcePersistenceImpl::implStoreAtLocation
1156 (
1157 const ::rtl::OUString& Location,
1158 const ::rtl::OUString& aNameBase,
1159 const ::rtl::OUString& aComment,
1160 const Reference< ucb::XSimpleFileAccess >& xFileAccess,
1161 bool bUsedForStore,
1162 bool bStoreAll,
1163 bool bKillAll
1164 )
1165 {
1166 // Delete files for deleted locales
1167 if( bUsedForStore || bKillAll )
1168 implKillRemovedLocaleFiles( Location, aNameBase, xFileAccess );
1169
1170 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
1171 {
1172 LocaleItem* pLocaleItem = *it;
1173 if( pLocaleItem != NULL && (bStoreAll || bKillAll || pLocaleItem->m_bModified) &&
1174 loadLocale( pLocaleItem ) )
1175 {
1176 ::rtl::OUString aCompleteFileName =
1177 implGetPathForLocaleItem( pLocaleItem, aNameBase, Location );
1178 if( xFileAccess->exists( aCompleteFileName ) )
1179 xFileAccess->kill( aCompleteFileName );
1180
1181 if( !bKillAll )
1182 {
1183 // Create Output stream
1184 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1185 if( xOutputStream.is() )
1186 {
1187 implWritePropertiesFile( pLocaleItem, xOutputStream, aComment );
1188 xOutputStream->closeOutput();
1189 }
1190 if( bUsedForStore )
1191 pLocaleItem->m_bModified = false;
1192 }
1193 }
1194 }
1195
1196 // Delete files for changed defaults
1197 if( bUsedForStore || bKillAll )
1198 implKillChangedDefaultFiles( Location, aNameBase, xFileAccess );
1199
1200 // Default locale
1201 if( m_pDefaultLocaleItem != NULL && (bStoreAll || bKillAll || m_bDefaultModified) )
1202 {
1203 ::rtl::OUString aCompleteFileName =
1204 implGetPathForLocaleItem( m_pDefaultLocaleItem, aNameBase, Location, true );
1205 if( xFileAccess->exists( aCompleteFileName ) )
1206 xFileAccess->kill( aCompleteFileName );
1207
1208 if( !bKillAll )
1209 {
1210 // Create Output stream
1211 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1212 if( xOutputStream.is() )
1213 xOutputStream->closeOutput();
1214
1215 if( bUsedForStore )
1216 m_bDefaultModified = false;
1217 }
1218 }
1219 }
1220
1221
1222 // -----------------------------------------------------------------------------
1223 // BinaryOutput, helper class for exportBinary
1224
1225 class BinaryOutput
1226 {
1227 Reference< XMultiComponentFactory > m_xMCF;
1228 Reference< XComponentContext > m_xContext;
1229 Reference< XInterface > m_xTempFile;
1230 Reference< io::XOutputStream > m_xOutputStream;
1231
1232 public:
1233 BinaryOutput( Reference< XMultiComponentFactory > xMCF,
1234 Reference< XComponentContext > xContext );
1235
getOutputStream(void)1236 Reference< io::XOutputStream > getOutputStream( void )
1237 { return m_xOutputStream; }
1238
1239 Sequence< ::sal_Int8 > closeAndGetData( void );
1240
1241 // Template to be used with sal_Int16 and sal_Unicode
1242 template< class T >
1243 void write16BitInt( T n );
writeInt16(sal_Int16 n)1244 void writeInt16( sal_Int16 n )
1245 { write16BitInt( n ); }
writeUnicodeChar(sal_Unicode n)1246 void writeUnicodeChar( sal_Unicode n )
1247 { write16BitInt( n ); }
1248 void writeInt32( sal_Int32 n );
1249 void writeString( const ::rtl::OUString& aStr );
1250 };
1251
BinaryOutput(Reference<XMultiComponentFactory> xMCF,Reference<XComponentContext> xContext)1252 BinaryOutput::BinaryOutput( Reference< XMultiComponentFactory > xMCF,
1253 Reference< XComponentContext > xContext )
1254 : m_xMCF( xMCF )
1255 , m_xContext( xContext )
1256 {
1257 m_xTempFile = m_xMCF->createInstanceWithContext
1258 ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ), m_xContext );
1259 if( m_xTempFile.is() )
1260 m_xOutputStream = Reference< io::XOutputStream >( m_xTempFile, UNO_QUERY );
1261 }
1262
1263 template< class T >
write16BitInt(T n)1264 void BinaryOutput::write16BitInt( T n )
1265 {
1266 if( !m_xOutputStream.is() )
1267 return;
1268
1269 Sequence< sal_Int8 > aSeq( 2 );
1270 sal_Int8* p = aSeq.getArray();
1271
1272 sal_Int8 nLow = sal_Int8( n & 0xff );
1273 sal_Int8 nHigh = sal_Int8( n >> 8 );
1274
1275 p[0] = nLow;
1276 p[1] = nHigh;
1277 m_xOutputStream->writeBytes( aSeq );
1278 }
1279
writeInt32(sal_Int32 n)1280 void BinaryOutput::writeInt32( sal_Int32 n )
1281 {
1282 if( !m_xOutputStream.is() )
1283 return;
1284
1285 Sequence< sal_Int8 > aSeq( 4 );
1286 sal_Int8* p = aSeq.getArray();
1287
1288 for( sal_Int16 i = 0 ; i < 4 ; i++ )
1289 {
1290 p[i] = sal_Int8( n & 0xff );
1291 n >>= 8;
1292 }
1293 m_xOutputStream->writeBytes( aSeq );
1294 }
1295
writeString(const::rtl::OUString & aStr)1296 void BinaryOutput::writeString( const ::rtl::OUString& aStr )
1297 {
1298 sal_Int32 nLen = aStr.getLength();
1299 const sal_Unicode* pStr = aStr.getStr();
1300
1301 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1302 writeUnicodeChar( pStr[i] );
1303
1304 writeUnicodeChar( 0 );
1305 }
1306
closeAndGetData(void)1307 Sequence< ::sal_Int8 > BinaryOutput::closeAndGetData( void )
1308 {
1309 Sequence< ::sal_Int8 > aRetSeq;
1310 if( !m_xOutputStream.is() )
1311 return aRetSeq;
1312
1313 m_xOutputStream->closeOutput();
1314
1315 Reference< io::XSeekable> xSeekable( m_xTempFile, UNO_QUERY );
1316 if( !xSeekable.is() )
1317 return aRetSeq;
1318
1319 sal_Int32 nSize = (sal_Int32)xSeekable->getPosition();
1320
1321 Reference< io::XInputStream> xInputStream( m_xTempFile, UNO_QUERY );
1322 if( !xInputStream.is() )
1323 return aRetSeq;
1324
1325 xSeekable->seek( 0 );
1326 sal_Int32 nRead = xInputStream->readBytes( aRetSeq, nSize );
1327 (void)nRead;
1328 OSL_ENSURE( nRead == nSize, "BinaryOutput::closeAndGetData: nRead != nSize" );
1329
1330 return aRetSeq;
1331 }
1332
1333
1334 // Binary format:
1335
1336 // Header
1337 // Byte Content
1338 // 0 + 1 sal_Int16: Version, currently 0, low byte first
1339 // 2 + 3 sal_Int16: Locale count = n, low byte first
1340 // 4 + 5 sal_Int16: Default Locale position in Locale list, == n if none
1341 // 6 - 7 sal_Int32: Start index locale block 0, lowest byte first
1342 // (n-1) * sal_Int32: Start index locale block 1 to n, lowest byte first
1343 // 6 + 4*n sal_Int32: "Start index" non existing locale block n+1,
1344 // marks the first invalid index, kind of EOF
1345
1346 // Locale block
1347 // All strings are stored as 2-Byte-0 terminated sequence
1348 // of 16 bit Unicode characters, each with low byte first
1349 // Empty strings only contain the 2-Byte-0
1350
1351 // Members of com.sun.star.lang.Locale
1352 // with l1 = Locale.Language.getLength()
1353 // with l2 = Locale.Country.getLength()
1354 // with l3 = Locale.Variant.getLength()
1355 // pos0 = 0 Locale.Language
1356 // pos1 = 2 * (l1 + 1) Locale.Country
1357 // pos2 = pos1 + 2 * (l2 + 1) Locale.Variant
1358 // pos3 = pos2 + 2 * (l3 + 1)
1359 // pos3 Properties file written by implWritePropertiesFile
1360
exportBinary()1361 Sequence< sal_Int8 > StringResourcePersistenceImpl::exportBinary( )
1362 {
1363 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1364 BinaryOutput aOut( xMCF, m_xContext );
1365
1366 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
1367 Sequence< sal_Int8 >* pLocaleDataSeq = new Sequence< sal_Int8 >[ nLocaleCount ];
1368
1369 sal_Int32 iLocale = 0;
1370 sal_Int32 iDefault = 0;
1371 for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin();
1372 it != m_aLocaleItemVector.end(); it++,iLocale++ )
1373 {
1374 LocaleItem* pLocaleItem = *it;
1375 if( pLocaleItem != NULL && loadLocale( pLocaleItem ) )
1376 {
1377 if( m_pDefaultLocaleItem == pLocaleItem )
1378 iDefault = iLocale;
1379
1380 BinaryOutput aLocaleOut( m_xMCF, m_xContext );
1381 implWriteLocaleBinary( pLocaleItem, aLocaleOut );
1382
1383 pLocaleDataSeq[iLocale] = aLocaleOut.closeAndGetData();
1384 }
1385 }
1386
1387 // Write header
1388 sal_Int16 nVersion = 0;
1389 sal_Int16 nLocaleCount16 = (sal_Int16)nLocaleCount;
1390 sal_Int16 iDefault16 = (sal_Int16)iDefault;
1391 aOut.writeInt16( nVersion );
1392 aOut.writeInt16( nLocaleCount16 );
1393 aOut.writeInt16( iDefault16 );
1394
1395 // Write data positions
1396 sal_Int32 nDataPos = 6 + 4 * (nLocaleCount + 1);
1397 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1398 {
1399 aOut.writeInt32( nDataPos );
1400
1401 Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale];
1402 sal_Int32 nSeqLen = rSeq.getLength();
1403 nDataPos += nSeqLen;
1404 }
1405 // Write final position
1406 aOut.writeInt32( nDataPos );
1407
1408 // Write data
1409 Reference< io::XOutputStream > xOutputStream = aOut.getOutputStream();
1410 if( xOutputStream.is() )
1411 {
1412 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1413 {
1414 Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale];
1415 xOutputStream->writeBytes( rSeq );
1416 }
1417 }
1418
1419 delete[] pLocaleDataSeq;
1420
1421 Sequence< sal_Int8 > aRetSeq = aOut.closeAndGetData();
1422 return aRetSeq;
1423 }
1424
implWriteLocaleBinary(LocaleItem * pLocaleItem,BinaryOutput & rOut)1425 void StringResourcePersistenceImpl::implWriteLocaleBinary
1426 ( LocaleItem* pLocaleItem, BinaryOutput& rOut )
1427 {
1428 Reference< io::XOutputStream > xOutputStream = rOut.getOutputStream();
1429 if( !xOutputStream.is() )
1430 return;
1431
1432 Locale& rLocale = pLocaleItem->m_locale;
1433 rOut.writeString( rLocale.Language );
1434 rOut.writeString( rLocale.Country );
1435 rOut.writeString( rLocale.Variant );
1436 implWritePropertiesFile( pLocaleItem, xOutputStream, m_aComment );
1437 }
1438
1439 // -----------------------------------------------------------------------------
1440 // BinaryOutput, helper class for exportBinary
1441
1442 class BinaryInput
1443 {
1444 Sequence< sal_Int8 > m_aData;
1445 Reference< XMultiComponentFactory > m_xMCF;
1446 Reference< XComponentContext > m_xContext;
1447
1448 const sal_Int8* m_pData;
1449 sal_Int32 m_nCurPos;
1450 sal_Int32 m_nSize;
1451
1452 public:
1453 BinaryInput( Sequence< ::sal_Int8 > aData, Reference< XMultiComponentFactory > xMCF,
1454 Reference< XComponentContext > xContext );
1455
1456 Reference< io::XInputStream > getInputStreamForSection( sal_Int32 nSize );
1457
1458 void seek( sal_Int32 nPos );
getPosition(void)1459 sal_Int32 getPosition( void )
1460 { return m_nCurPos; }
1461
1462 sal_Int16 readInt16( void );
1463 sal_Int32 readInt32( void );
1464 sal_Unicode readUnicodeChar( void );
1465 ::rtl::OUString readString( void );
1466 };
1467
BinaryInput(Sequence<::sal_Int8> aData,Reference<XMultiComponentFactory> xMCF,Reference<XComponentContext> xContext)1468 BinaryInput::BinaryInput( Sequence< ::sal_Int8 > aData, Reference< XMultiComponentFactory > xMCF,
1469 Reference< XComponentContext > xContext )
1470 : m_aData( aData )
1471 , m_xMCF( xMCF )
1472 , m_xContext( xContext )
1473 {
1474 m_pData = m_aData.getConstArray();
1475 m_nCurPos = 0;
1476 m_nSize = m_aData.getLength();
1477 }
1478
getInputStreamForSection(sal_Int32 nSize)1479 Reference< io::XInputStream > BinaryInput::getInputStreamForSection( sal_Int32 nSize )
1480 {
1481 Reference< io::XInputStream > xIn;
1482 if( m_nCurPos + nSize <= m_nSize )
1483 {
1484 Reference< io::XOutputStream > xTempOut( m_xMCF->createInstanceWithContext
1485 ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ), m_xContext ), UNO_QUERY );
1486 if( xTempOut.is() )
1487 {
1488 Sequence< sal_Int8 > aSection( m_pData + m_nCurPos, nSize );
1489 xTempOut->writeBytes( aSection );
1490
1491 Reference< io::XSeekable> xSeekable( xTempOut, UNO_QUERY );
1492 if( xSeekable.is() )
1493 xSeekable->seek( 0 );
1494
1495 xIn = Reference< io::XInputStream>( xTempOut, UNO_QUERY );
1496 }
1497 }
1498 else
1499 OSL_ENSURE( false, "BinaryInput::getInputStreamForSection(): Read past end" );
1500
1501 return xIn;
1502 }
1503
seek(sal_Int32 nPos)1504 void BinaryInput::seek( sal_Int32 nPos )
1505 {
1506 if( nPos <= m_nSize )
1507 m_nCurPos = nPos;
1508 else
1509 OSL_ENSURE( false, "BinaryInput::seek(): Position past end" );
1510 }
1511
1512
readInt16(void)1513 sal_Int16 BinaryInput::readInt16( void )
1514 {
1515 sal_Int16 nRet = 0;
1516 if( m_nCurPos + 2 <= m_nSize )
1517 {
1518 nRet = nRet + sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1519 nRet += 256 * sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1520 }
1521 else
1522 OSL_ENSURE( false, "BinaryInput::readInt16(): Read past end" );
1523
1524 return nRet;
1525 }
1526
readInt32(void)1527 sal_Int32 BinaryInput::readInt32( void )
1528 {
1529 sal_Int32 nRet = 0;
1530 if( m_nCurPos + 4 <= m_nSize )
1531 {
1532 sal_Int32 nFactor = 1;
1533 for( sal_Int16 i = 0; i < 4; i++ )
1534 {
1535 nRet += sal_uInt8( m_pData[m_nCurPos++] ) * nFactor;
1536 nFactor *= 256;
1537 }
1538 }
1539 else
1540 OSL_ENSURE( false, "BinaryInput::readInt32(): Read past end" );
1541
1542 return nRet;
1543 }
1544
readUnicodeChar(void)1545 sal_Unicode BinaryInput::readUnicodeChar( void )
1546 {
1547 sal_uInt16 nRet = 0;
1548 if( m_nCurPos + 2 <= m_nSize )
1549 {
1550 nRet = nRet + sal_uInt8( m_pData[m_nCurPos++] );
1551 nRet += 256 * sal_uInt8( m_pData[m_nCurPos++] );
1552 }
1553 else
1554 OSL_ENSURE( false, "BinaryInput::readUnicodeChar(): Read past end" );
1555
1556 sal_Unicode cRet = nRet;
1557 return cRet;
1558 }
1559
readString(void)1560 ::rtl::OUString BinaryInput::readString( void )
1561 {
1562 ::rtl::OUStringBuffer aBuf;
1563 sal_Unicode c;
1564 do
1565 {
1566 c = readUnicodeChar();
1567 if( c != 0 )
1568 aBuf.append( c );
1569 }
1570 while( c != 0 );
1571
1572 ::rtl::OUString aRetStr = aBuf.makeStringAndClear();
1573 return aRetStr;
1574 }
1575
importBinary(const Sequence<::sal_Int8> & Data)1576 void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
1577 {
1578 // Init: Remove all locales
1579 sal_Int32 nOldLocaleCount = 0;
1580 do
1581 {
1582 Sequence< Locale > aLocaleSeq = getLocales();
1583 nOldLocaleCount = aLocaleSeq.getLength();
1584 if( nOldLocaleCount > 0 )
1585 {
1586 Locale aLocale = aLocaleSeq[0];
1587 removeLocale( aLocale );
1588 }
1589 }
1590 while( nOldLocaleCount > 0 );
1591
1592 // Import data
1593 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1594 BinaryInput aIn( Data, xMCF, m_xContext );
1595
1596 sal_Int32 nVersion = aIn.readInt16();
1597 (void)nVersion;
1598 sal_Int32 nLocaleCount = aIn.readInt16();
1599 sal_Int32 iDefault = aIn.readInt16();
1600 (void)iDefault;
1601
1602 sal_Int32* pPositions = new sal_Int32[nLocaleCount + 1];
1603 for( sal_Int32 i = 0; i < nLocaleCount + 1; i++ )
1604 pPositions[i] = aIn.readInt32();
1605
1606 // Import locales
1607 LocaleItem* pUseAsDefaultItem = NULL;
1608 for( sal_Int32 i = 0; i < nLocaleCount; i++ )
1609 {
1610 sal_Int32 nPos = pPositions[i];
1611 aIn.seek( nPos );
1612
1613 Locale aLocale;
1614 aLocale.Language = aIn.readString();
1615 aLocale.Country = aIn.readString();
1616 aLocale.Variant = aIn.readString();
1617
1618 sal_Int32 nAfterStringPos = aIn.getPosition();
1619 sal_Int32 nSize = pPositions[i+1] - nAfterStringPos;
1620 Reference< io::XInputStream > xInput = aIn.getInputStreamForSection( nSize );
1621 if( xInput.is() )
1622 {
1623 LocaleItem* pLocaleItem = new LocaleItem( aLocale );
1624 if( iDefault == i )
1625 pUseAsDefaultItem = pLocaleItem;
1626 m_aLocaleItemVector.push_back( pLocaleItem );
1627 implReadPropertiesFile( pLocaleItem, xInput );
1628 }
1629 }
1630
1631 if( pUseAsDefaultItem != NULL )
1632 setDefaultLocale( pUseAsDefaultItem->m_locale );
1633
1634 delete[] pPositions;
1635 }
1636
1637
1638 // =============================================================================
1639 // Private helper methods
1640
checkNamingSceme(const::rtl::OUString & aName,const::rtl::OUString & aNameBase,Locale & aLocale)1641 bool checkNamingSceme( const ::rtl::OUString& aName, const ::rtl::OUString& aNameBase,
1642 Locale& aLocale )
1643 {
1644 bool bSuccess = false;
1645
1646 sal_Int32 nNameLen = aName.getLength();
1647 sal_Int32 nNameBaseLen = aNameBase.getLength();
1648
1649 // Name has to start with NameBase followed
1650 // by a '_' and at least one more character
1651 if( aName.indexOf( aNameBase ) == 0 && nNameBaseLen < nNameLen-1 &&
1652 aName.getStr()[nNameBaseLen] == '_' )
1653 {
1654 bSuccess = true;
1655
1656 sal_Int32 iStart = nNameBaseLen + 1;
1657 sal_Int32 iNext_ = aName.indexOf( '_', iStart );
1658 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1659 {
1660 aLocale.Language = aName.copy( iStart, iNext_ - iStart );
1661
1662 iStart = iNext_ + 1;
1663 iNext_ = aName.indexOf( '_', iStart );
1664 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1665 {
1666 aLocale.Country = aName.copy( iStart, iNext_ - iStart );
1667 aLocale.Variant = aName.copy( iNext_ + 1 );
1668 }
1669 else
1670 aLocale.Country = aName.copy( iStart );
1671 }
1672 else
1673 aLocale.Language = aName.copy( iStart );
1674 }
1675 return bSuccess;
1676 }
1677
implLoadAllLocales(void)1678 void StringResourcePersistenceImpl::implLoadAllLocales( void )
1679 {
1680 for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ )
1681 {
1682 LocaleItem* pLocaleItem = *it;
1683 if( pLocaleItem != NULL )
1684 loadLocale( pLocaleItem );
1685 }
1686 }
1687
1688 // Scan locale properties files helper
implScanLocaleNames(const Sequence<::rtl::OUString> & aContentSeq)1689 void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< ::rtl::OUString >& aContentSeq )
1690 {
1691 Locale aDefaultLocale;
1692 bool bDefaultFound = false;
1693
1694 sal_Int32 nCount = aContentSeq.getLength();
1695 const ::rtl::OUString* pFiles = aContentSeq.getConstArray();
1696 for( int i = 0 ; i < nCount ; i++ )
1697 {
1698 ::rtl::OUString aCompleteName = pFiles[i];
1699 rtl::OUString aPureName;
1700 rtl::OUString aExtension;
1701 sal_Int32 iDot = aCompleteName.lastIndexOf( '.' );
1702 sal_Int32 iSlash = aCompleteName.lastIndexOf( '/' );
1703 if( iDot != -1 )
1704 {
1705 sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0;
1706 aPureName = aCompleteName.copy( iCopyFrom, iDot-iCopyFrom );
1707 aExtension = aCompleteName.copy( iDot + 1 );
1708 }
1709
1710 if( aExtension.equalsAscii( "properties" ) )
1711 {
1712 //rtl::OUString aName = aInetObj.getBase();
1713 Locale aLocale;
1714
1715 if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) )
1716 {
1717 LocaleItem* pLocaleItem = new LocaleItem( aLocale, false );
1718 m_aLocaleItemVector.push_back( pLocaleItem );
1719
1720 if( m_pCurrentLocaleItem == NULL )
1721 m_pCurrentLocaleItem = pLocaleItem;
1722
1723 if( m_pDefaultLocaleItem == NULL )
1724 {
1725 m_pDefaultLocaleItem = pLocaleItem;
1726 m_bDefaultModified = true;
1727 }
1728 }
1729 }
1730 else if( !bDefaultFound && aExtension.equalsAscii( "default" ) )
1731 {
1732 //rtl::OUString aName = aInetObj.getBase();
1733 Locale aLocale;
1734
1735 if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) )
1736 bDefaultFound = true;
1737 }
1738 }
1739 if( bDefaultFound )
1740 {
1741 LocaleItem* pLocaleItem = getItemForLocale( aDefaultLocale, false );
1742 if( pLocaleItem )
1743 {
1744 m_pDefaultLocaleItem = pLocaleItem;
1745 m_bDefaultModified = false;
1746 }
1747 }
1748 }
1749
1750 // Scan locale properties files
implScanLocales(void)1751 void StringResourcePersistenceImpl::implScanLocales( void )
1752 {
1753 // Dummy implementation, method not called for this
1754 // base class, but pure virtual not possible-
1755 }
1756
loadLocale(LocaleItem * pLocaleItem)1757 bool StringResourcePersistenceImpl::loadLocale( LocaleItem* pLocaleItem )
1758 {
1759 bool bSuccess = false;
1760
1761 OSL_ENSURE( pLocaleItem, "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL" );
1762 if( pLocaleItem )
1763 {
1764 if( pLocaleItem->m_bLoaded )
1765 {
1766 bSuccess = true;
1767 }
1768 else
1769 {
1770 bSuccess = implLoadLocale( pLocaleItem );
1771 pLocaleItem->m_bLoaded = true; // = bSuccess??? -> leads to more tries
1772 }
1773 }
1774 return bSuccess;
1775 }
1776
implLoadLocale(LocaleItem *)1777 bool StringResourcePersistenceImpl::implLoadLocale( LocaleItem* )
1778 {
1779 // Dummy implementation, method not called for this
1780 // base class, but pure virtual not possible-
1781 return false;
1782 }
1783
implGetNameScemeForLocaleItem(const LocaleItem * pLocaleItem)1784 ::rtl::OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem )
1785 {
1786 static ::rtl::OUString aUnder = ::rtl::OUString::createFromAscii( "_" );
1787
1788 OSL_ENSURE( pLocaleItem,
1789 "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL" );
1790 Locale aLocale = pLocaleItem->m_locale;
1791
1792 ::rtl::OUString aRetStr = aUnder;
1793 aRetStr += aLocale.Language;
1794
1795 ::rtl::OUString aCountry = aLocale.Country;
1796 if( aCountry.getLength() )
1797 {
1798 aRetStr += aUnder;
1799 aRetStr += aCountry;
1800 }
1801
1802 ::rtl::OUString aVariant = aLocale.Variant;
1803 if( aVariant.getLength() )
1804 {
1805 aRetStr += aUnder;
1806 aRetStr += aVariant;
1807 }
1808 return aRetStr;
1809 }
1810
implGetFileNameForLocaleItem(LocaleItem * pLocaleItem,const::rtl::OUString & aNameBase)1811 ::rtl::OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem
1812 ( LocaleItem* pLocaleItem, const ::rtl::OUString& aNameBase )
1813 {
1814 ::rtl::OUString aFileName = aNameBase;
1815 if( aFileName.getLength() == 0 )
1816 aFileName = aNameBaseDefaultStr;
1817
1818 aFileName += implGetNameScemeForLocaleItem( pLocaleItem );
1819 return aFileName;
1820 }
1821
implGetPathForLocaleItem(LocaleItem * pLocaleItem,const::rtl::OUString & aNameBase,const::rtl::OUString & aLocation,bool bDefaultFile)1822 ::rtl::OUString StringResourcePersistenceImpl::implGetPathForLocaleItem
1823 ( LocaleItem* pLocaleItem, const ::rtl::OUString& aNameBase,
1824 const ::rtl::OUString& aLocation, bool bDefaultFile )
1825 {
1826 ::rtl::OUString aFileName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1827 INetURLObject aInetObj( aLocation );
1828 aInetObj.insertName( aFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL );
1829 if( bDefaultFile )
1830 aInetObj.setExtension( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("default") ) );
1831 else
1832 aInetObj.setExtension( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("properties") ) );
1833 ::rtl::OUString aCompleteFileName = aInetObj.GetMainURL( INetURLObject::NO_DECODE );
1834 return aCompleteFileName;
1835 }
1836
1837 // White space according to Java property files specification in
1838 // http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)
isWhiteSpace(sal_Unicode c)1839 inline bool isWhiteSpace( sal_Unicode c )
1840 {
1841 bool bWhite = ( c == 0x0020 || // space
1842 c == 0x0009 || // tab
1843 c == 0x000a || // line feed, not always handled by TextInputStream
1844 c == 0x000d || // carriage return, not always handled by TextInputStream
1845 c == 0x000C ); // form feed
1846 return bWhite;
1847 }
1848
skipWhites(const sal_Unicode * pBuf,sal_Int32 nLen,sal_Int32 & ri)1849 inline void skipWhites( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1850 {
1851 while( ri < nLen )
1852 {
1853 if( !isWhiteSpace( pBuf[ri] ) )
1854 break;
1855 ri++;
1856 }
1857 }
1858
isHexDigit(sal_Unicode c,sal_uInt16 & nDigitVal)1859 inline bool isHexDigit( sal_Unicode c, sal_uInt16& nDigitVal )
1860 {
1861 bool bRet = true;
1862 if( c >= '0' && c <= '9' )
1863 nDigitVal = c - '0';
1864 else if( c >= 'a' && c <= 'f' )
1865 nDigitVal = c - 'a' + 10;
1866 else if( c >= 'A' && c <= 'F' )
1867 nDigitVal = c - 'A' + 10;
1868 else
1869 bRet = false;
1870 return bRet;
1871 }
1872
getEscapeChar(const sal_Unicode * pBuf,sal_Int32 nLen,sal_Int32 & ri)1873 sal_Unicode getEscapeChar( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1874 {
1875 sal_Int32 i = ri;
1876
1877 sal_Unicode cRet = 0;
1878 sal_Unicode c = pBuf[i];
1879 switch( c )
1880 {
1881 case 't':
1882 cRet = 0x0009;
1883 break;
1884 case 'n':
1885 cRet = 0x000a;
1886 break;
1887 case 'f':
1888 cRet = 0x000c;
1889 break;
1890 case 'r':
1891 cRet = 0x000d;
1892 break;
1893 case '\\':
1894 cRet = '\\';
1895 break;
1896 case 'u':
1897 {
1898 // Skip multiple u
1899 i++;
1900 while( i < nLen && pBuf[i] == 'u' )
1901 i++;
1902
1903 // Process hex digits
1904 sal_Int32 nDigitCount = 0;
1905 sal_uInt16 nDigitVal;
1906 while( i < nLen && isHexDigit( pBuf[i], nDigitVal ) )
1907 {
1908 cRet = 16 * cRet + nDigitVal;
1909
1910 nDigitCount++;
1911 if( nDigitCount == 4 )
1912 {
1913 // Write back position
1914 ri = i;
1915 break;
1916 }
1917 i++;
1918 }
1919 break;
1920 }
1921 default:
1922 cRet = c;
1923 }
1924
1925 return cRet;
1926 }
1927
CheckContinueInNextLine(Reference<io::XTextInputStream> xTextInputStream,::rtl::OUString & aLine,bool & bEscapePending,const sal_Unicode * & pBuf,sal_Int32 & nLen,sal_Int32 & i)1928 void CheckContinueInNextLine( Reference< io::XTextInputStream > xTextInputStream,
1929 ::rtl::OUString& aLine, bool& bEscapePending, const sal_Unicode*& pBuf,
1930 sal_Int32& nLen, sal_Int32& i )
1931 {
1932 if( i == nLen && bEscapePending )
1933 {
1934 bEscapePending = false;
1935
1936 if( !xTextInputStream->isEOF() )
1937 {
1938 aLine = xTextInputStream->readLine();
1939 nLen = aLine.getLength();
1940 pBuf = aLine.getStr();
1941 i = 0;
1942
1943 skipWhites( pBuf, nLen, i );
1944 }
1945 }
1946 }
1947
implReadPropertiesFile(LocaleItem * pLocaleItem,const Reference<io::XInputStream> & xInputStream)1948 bool StringResourcePersistenceImpl::implReadPropertiesFile
1949 ( LocaleItem* pLocaleItem, const Reference< io::XInputStream >& xInputStream )
1950 {
1951 if( !xInputStream.is() || pLocaleItem == NULL )
1952 return false;
1953
1954 bool bSuccess = false;
1955 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
1956 Reference< io::XTextInputStream > xTextInputStream( xMCF->createInstanceWithContext
1957 ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextInputStream" ), m_xContext ), UNO_QUERY );
1958
1959 if( xTextInputStream.is() )
1960 {
1961 Reference< io::XActiveDataSink> xActiveDataSink( xTextInputStream, UNO_QUERY );
1962 if( xActiveDataSink.is() )
1963 {
1964 bSuccess = true;
1965
1966 xActiveDataSink->setInputStream( xInputStream );
1967
1968 ::rtl::OUString aEncodingStr = ::rtl::OUString::createFromAscii
1969 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
1970 xTextInputStream->setEncoding( aEncodingStr );
1971
1972 ::rtl::OUString aLine;
1973 while( !xTextInputStream->isEOF() )
1974 {
1975 aLine = xTextInputStream->readLine();
1976
1977 sal_Int32 nLen = aLine.getLength();
1978 if( 0 == nLen )
1979 continue;
1980 const sal_Unicode* pBuf = aLine.getStr();
1981 ::rtl::OUStringBuffer aBuf;
1982 sal_Unicode c = 0;
1983 sal_Int32 i = 0;
1984
1985 skipWhites( pBuf, nLen, i );
1986 if( i == nLen )
1987 continue; // line contains only white spaces
1988
1989 // Comment?
1990 c = pBuf[i];
1991 if( c == '#' || c == '!' )
1992 continue;
1993
1994 // Scan key
1995 ::rtl::OUString aResourceID;
1996 bool bEscapePending = false;
1997 bool bStrComplete = false;
1998 while( i < nLen && !bStrComplete )
1999 {
2000 c = pBuf[i];
2001 if( bEscapePending )
2002 {
2003 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
2004 bEscapePending = false;
2005 }
2006 else
2007 {
2008 if( c == '\\' )
2009 {
2010 bEscapePending = true;
2011 }
2012 else
2013 {
2014 if( c == ':' || c == '=' || isWhiteSpace( c ) )
2015 bStrComplete = true;
2016 else
2017 aBuf.append( c );
2018 }
2019 }
2020 i++;
2021
2022 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
2023 if( i == nLen )
2024 bStrComplete = true;
2025
2026 if( bStrComplete )
2027 aResourceID = aBuf.makeStringAndClear();
2028 }
2029
2030 // Ignore lines with empty keys
2031 if( 0 == aResourceID.getLength() )
2032 continue;
2033
2034 // Scan value
2035 skipWhites( pBuf, nLen, i );
2036
2037 ::rtl::OUString aValueStr;
2038 bEscapePending = false;
2039 bStrComplete = false;
2040 while( i < nLen && !bStrComplete )
2041 {
2042 c = pBuf[i];
2043 if( c == 0x000a || c == 0x000d ) // line feed/carriage return, not always handled by TextInputStream
2044 {
2045 i++;
2046 }
2047 else
2048 {
2049 if( bEscapePending )
2050 {
2051 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
2052 bEscapePending = false;
2053 }
2054 else if( c == '\\' )
2055 bEscapePending = true;
2056 else
2057 aBuf.append( c );
2058 i++;
2059
2060 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
2061 }
2062 if( i == nLen )
2063 bStrComplete = true;
2064
2065 if( bStrComplete )
2066 aValueStr = aBuf.makeStringAndClear();
2067 }
2068
2069 // Push into table
2070 pLocaleItem->m_aIdToStringMap[ aResourceID ] = aValueStr;
2071 implScanIdForNumber( aResourceID );
2072 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
2073 rIndexMap[ aResourceID ] = pLocaleItem->m_nNextIndex++;
2074 }
2075 }
2076 }
2077
2078 return bSuccess;
2079 }
2080
2081
getHexCharForDigit(sal_uInt16 nDigitVal)2082 inline sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal )
2083 {
2084 sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10));
2085 return cRet;
2086 }
2087
implWriteCharToBuffer(::rtl::OUStringBuffer & aBuf,sal_Unicode cu,bool bKey)2088 void implWriteCharToBuffer( ::rtl::OUStringBuffer& aBuf, sal_Unicode cu, bool bKey )
2089 {
2090 if( cu == '\\' )
2091 {
2092 aBuf.append( (sal_Unicode)'\\' );
2093 aBuf.append( (sal_Unicode)'\\' );
2094 }
2095 else if( cu == 0x000a )
2096 {
2097 aBuf.append( (sal_Unicode)'\\' );
2098 aBuf.append( (sal_Unicode)'n' );
2099 }
2100 else if( cu == 0x000d )
2101 {
2102 aBuf.append( (sal_Unicode)'\\' );
2103 aBuf.append( (sal_Unicode)'r' );
2104 }
2105 else if( bKey && cu == '=' )
2106 {
2107 aBuf.append( (sal_Unicode)'\\' );
2108 aBuf.append( (sal_Unicode)'=' );
2109 }
2110 else if( bKey && cu == ':' )
2111 {
2112 aBuf.append( (sal_Unicode)'\\' );
2113 aBuf.append( (sal_Unicode)':' );
2114 }
2115 // ISO/IEC 8859-1 range according to:
2116 // http://en.wikipedia.org/wiki/ISO/IEC_8859-1
2117 else if( (cu >= 0x20 && cu <= 0x7e) )
2118 //TODO: Check why (cu >= 0xa0 && cu <= 0xFF)
2119 //is encoded in sample properties files
2120 //else if( (cu >= 0x20 && cu <= 0x7e) ||
2121 // (cu >= 0xa0 && cu <= 0xFF) )
2122 {
2123 aBuf.append( cu );
2124 }
2125 else
2126 {
2127 // Unicode encoding
2128 aBuf.append( (sal_Unicode)'\\' );
2129 aBuf.append( (sal_Unicode)'u' );
2130
2131 sal_uInt16 nVal = cu;
2132 for( sal_uInt16 i = 0 ; i < 4 ; i++ )
2133 {
2134 sal_uInt16 nDigit = nVal / 0x1000;
2135 nVal -= nDigit * 0x1000;
2136 nVal *= 0x10;
2137 aBuf.append( getHexCharForDigit( nDigit ) );
2138 }
2139 }
2140 }
2141
implWriteStringWithEncoding(const::rtl::OUString & aStr,Reference<io::XTextOutputStream> xTextOutputStream,bool bKey)2142 void implWriteStringWithEncoding( const ::rtl::OUString& aStr,
2143 Reference< io::XTextOutputStream > xTextOutputStream, bool bKey )
2144 {
2145 static sal_Unicode cLineFeed = 0xa;
2146
2147 (void)aStr;
2148 (void)xTextOutputStream;
2149
2150 ::rtl::OUStringBuffer aBuf;
2151 sal_Int32 nLen = aStr.getLength();
2152 const sal_Unicode* pSrc = aStr.getStr();
2153 for( sal_Int32 i = 0 ; i < nLen ; i++ )
2154 {
2155 sal_Unicode cu = pSrc[i];
2156 implWriteCharToBuffer( aBuf, cu, bKey );
2157 // TODO?: split long lines
2158 }
2159 if( !bKey )
2160 aBuf.append( cLineFeed );
2161
2162 ::rtl::OUString aWriteStr = aBuf.makeStringAndClear();
2163 xTextOutputStream->writeString( aWriteStr );
2164 }
2165
implWritePropertiesFile(LocaleItem * pLocaleItem,const Reference<io::XOutputStream> & xOutputStream,const::rtl::OUString & aComment)2166 bool StringResourcePersistenceImpl::implWritePropertiesFile( LocaleItem* pLocaleItem,
2167 const Reference< io::XOutputStream >& xOutputStream, const ::rtl::OUString& aComment )
2168 {
2169 static ::rtl::OUString aAssignmentStr = ::rtl::OUString::createFromAscii( "=" );
2170 static ::rtl::OUString aLineFeedStr = ::rtl::OUString::createFromAscii( "\n" );
2171
2172 if( !xOutputStream.is() || pLocaleItem == NULL )
2173 return false;
2174
2175 bool bSuccess = false;
2176 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
2177 Reference< io::XTextOutputStream > xTextOutputStream( xMCF->createInstanceWithContext
2178 ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ), m_xContext ), UNO_QUERY );
2179
2180 if( xTextOutputStream.is() )
2181 {
2182 Reference< io::XActiveDataSource> xActiveDataSource( xTextOutputStream, UNO_QUERY );
2183 if( xActiveDataSource.is() )
2184 {
2185 xActiveDataSource->setOutputStream( xOutputStream );
2186
2187 ::rtl::OUString aEncodingStr = ::rtl::OUString::createFromAscii
2188 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
2189 xTextOutputStream->setEncoding( aEncodingStr );
2190
2191 xTextOutputStream->writeString( aComment );
2192 xTextOutputStream->writeString( aLineFeedStr );
2193
2194 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
2195 if( rHashMap.size() > 0 )
2196 {
2197 // Sort ids according to read order
2198 const IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
2199 IdToIndexMap::const_iterator it_index;
2200
2201 // Find max/min index
2202 sal_Int32 nMinIndex = -1;
2203 sal_Int32 nMaxIndex = -1;
2204 for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); it_index++ )
2205 {
2206 sal_Int32 nIndex = (*it_index).second;
2207 if( nMinIndex > nIndex || nMinIndex == -1 )
2208 nMinIndex = nIndex;
2209 if( nMaxIndex < nIndex )
2210 nMaxIndex = nIndex;
2211 }
2212 sal_Int32 nTabSize = nMaxIndex - nMinIndex + 1;
2213
2214 // Create sorted array of pointers to the id strings
2215 const ::rtl::OUString** pIdPtrs = new const ::rtl::OUString*[nTabSize];
2216 sal_Int32 i;
2217 for( i = 0 ; i < nTabSize ; i++ )
2218 pIdPtrs[i] = NULL;
2219 for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); it_index++ )
2220 {
2221 sal_Int32 nIndex = (*it_index).second;
2222 pIdPtrs[nIndex - nMinIndex] = &((*it_index).first);
2223 }
2224
2225 // Write lines in correct order
2226 for( i = 0 ; i < nTabSize ; i++ )
2227 {
2228 const ::rtl::OUString* pStr = pIdPtrs[i];
2229 if( pStr != NULL )
2230 {
2231 ::rtl::OUString aResourceID = *pStr;
2232 IdToStringMap::const_iterator it = rHashMap.find( aResourceID );
2233 if( !( it == rHashMap.end() ) )
2234 {
2235 implWriteStringWithEncoding( aResourceID, xTextOutputStream, true );
2236 xTextOutputStream->writeString( aAssignmentStr );
2237 ::rtl::OUString aValStr = (*it).second;
2238 implWriteStringWithEncoding( aValStr, xTextOutputStream, false );
2239 }
2240 }
2241 }
2242
2243 delete[] pIdPtrs;
2244 }
2245
2246 bSuccess = true;
2247 }
2248 }
2249 return bSuccess;
2250 }
2251
2252
2253 // =============================================================================
2254 // StringResourceWithStorageImpl
2255 // =============================================================================
2256
2257 // component operations
getSupportedServiceNames_StringResourceWithStorageImpl()2258 static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceWithStorageImpl()
2259 {
2260 Sequence< ::rtl::OUString > names(1);
2261 names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResourceWithStorage") );
2262 return names;
2263 }
2264
getImplementationName_StringResourceWithStorageImpl()2265 static ::rtl::OUString getImplementationName_StringResourceWithStorageImpl()
2266 {
2267 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResourceWithStorage") );
2268 }
2269
create_StringResourceWithStorageImpl(Reference<XComponentContext> const & xContext)2270 static Reference< XInterface > SAL_CALL create_StringResourceWithStorageImpl(
2271 Reference< XComponentContext > const & xContext )
2272 SAL_THROW( () )
2273 {
2274 return static_cast< ::cppu::OWeakObject * >( new StringResourceWithStorageImpl( xContext ) );
2275 }
2276
2277 // -----------------------------------------------------------------------------
2278
StringResourceWithStorageImpl(const Reference<XComponentContext> & rxContext)2279 StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext )
2280 : StringResourceWithStorageImpl_BASE( rxContext )
2281 , m_bStorageChanged( false )
2282 {
2283 }
2284
2285 // -----------------------------------------------------------------------------
2286
~StringResourceWithStorageImpl()2287 StringResourceWithStorageImpl::~StringResourceWithStorageImpl()
2288 {
2289 }
2290
2291 // -----------------------------------------------------------------------------
2292 // XServiceInfo
2293 // -----------------------------------------------------------------------------
2294
getImplementationName()2295 ::rtl::OUString StringResourceWithStorageImpl::getImplementationName( )
2296 {
2297 return getImplementationName_StringResourceWithStorageImpl();
2298 }
2299
2300 // -----------------------------------------------------------------------------
2301
supportsService(const::rtl::OUString & rServiceName)2302 sal_Bool StringResourceWithStorageImpl::supportsService( const ::rtl::OUString& rServiceName )
2303 {
2304 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
2305 const ::rtl::OUString* pNames = aNames.getConstArray();
2306 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
2307 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
2308 ;
2309
2310 return pNames != pEnd;
2311 }
2312
2313 // -----------------------------------------------------------------------------
2314
getSupportedServiceNames()2315 Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getSupportedServiceNames( )
2316 {
2317 return getSupportedServiceNames_StringResourceWithStorageImpl();
2318 }
2319
2320 // -----------------------------------------------------------------------------
2321 // XInitialization
2322 // -----------------------------------------------------------------------------
2323
initialize(const Sequence<Any> & aArguments)2324 void StringResourceWithStorageImpl::initialize( const Sequence< Any >& aArguments )
2325 {
2326 ::osl::MutexGuard aGuard( getMutex() );
2327
2328 if ( aArguments.getLength() != 5 )
2329 {
2330 throw RuntimeException(
2331 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringResourceWithStorageImpl::initialize: invalid number of arguments!" ) ),
2332 Reference< XInterface >() );
2333 }
2334
2335 bool bOk = (aArguments[0] >>= m_xStorage);
2336 if( bOk && !m_xStorage.is() )
2337 bOk = false;
2338
2339 if( !bOk )
2340 {
2341 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceWithStorageImpl::initialize: invalid storage" );
2342 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2343 }
2344
2345 implInitializeCommonParameters( aArguments );
2346 }
2347
2348 // -----------------------------------------------------------------------------
2349 // Forwarding calls to base class
2350
2351 // XModifyBroadcaster
addModifyListener(const Reference<XModifyListener> & aListener)2352 void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2353 {
2354 StringResourceImpl::addModifyListener( aListener );
2355 }
removeModifyListener(const Reference<XModifyListener> & aListener)2356 void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2357 {
2358 StringResourceImpl::removeModifyListener( aListener );
2359 }
2360
2361 // XStringResourceResolver
resolveString(const::rtl::OUString & ResourceID)2362 ::rtl::OUString StringResourceWithStorageImpl::resolveString( const ::rtl::OUString& ResourceID )
2363 {
2364 return StringResourceImpl::resolveString( ResourceID ) ;
2365 }
resolveStringForLocale(const::rtl::OUString & ResourceID,const Locale & locale)2366 ::rtl::OUString StringResourceWithStorageImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
2367 {
2368 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2369 }
hasEntryForId(const::rtl::OUString & ResourceID)2370 sal_Bool StringResourceWithStorageImpl::hasEntryForId( const ::rtl::OUString& ResourceID )
2371 {
2372 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2373 }
hasEntryForIdAndLocale(const::rtl::OUString & ResourceID,const Locale & locale)2374 sal_Bool StringResourceWithStorageImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID,
2375 const Locale& locale )
2376 {
2377 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2378 }
getResourceIDs()2379 Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getResourceIDs( )
2380 {
2381 return StringResourceImpl::getResourceIDs();
2382 }
getResourceIDsForLocale(const Locale & locale)2383 Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getResourceIDsForLocale
2384 ( const Locale& locale )
2385 {
2386 return StringResourceImpl::getResourceIDsForLocale( locale );
2387 }
getCurrentLocale()2388 Locale StringResourceWithStorageImpl::getCurrentLocale()
2389 {
2390 return StringResourceImpl::getCurrentLocale();
2391 }
getDefaultLocale()2392 Locale StringResourceWithStorageImpl::getDefaultLocale( )
2393 {
2394 return StringResourceImpl::getDefaultLocale();
2395 }
getLocales()2396 Sequence< Locale > StringResourceWithStorageImpl::getLocales( )
2397 {
2398 return StringResourceImpl::getLocales();
2399 }
2400
2401 // XStringResourceManager
isReadOnly()2402 sal_Bool StringResourceWithStorageImpl::isReadOnly()
2403 {
2404 return StringResourceImpl::isReadOnly();
2405 }
setCurrentLocale(const Locale & locale,sal_Bool FindClosestMatch)2406 void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2407 {
2408 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2409 }
setDefaultLocale(const Locale & locale)2410 void StringResourceWithStorageImpl::setDefaultLocale( const Locale& locale )
2411 {
2412 StringResourceImpl::setDefaultLocale( locale );
2413 }
setString(const::rtl::OUString & ResourceID,const::rtl::OUString & Str)2414 void StringResourceWithStorageImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str )
2415 {
2416 StringResourceImpl::setString( ResourceID, Str );
2417 }
setStringForLocale(const::rtl::OUString & ResourceID,const::rtl::OUString & Str,const Locale & locale)2418 void StringResourceWithStorageImpl::setStringForLocale
2419 ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale )
2420 {
2421 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2422 }
removeId(const::rtl::OUString & ResourceID)2423 void StringResourceWithStorageImpl::removeId( const ::rtl::OUString& ResourceID )
2424 {
2425 StringResourceImpl::removeId( ResourceID );
2426 }
removeIdForLocale(const::rtl::OUString & ResourceID,const Locale & locale)2427 void StringResourceWithStorageImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
2428 {
2429 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2430 }
newLocale(const Locale & locale)2431 void StringResourceWithStorageImpl::newLocale( const Locale& locale )
2432 {
2433 StringResourceImpl::newLocale( locale );
2434 }
removeLocale(const Locale & locale)2435 void StringResourceWithStorageImpl::removeLocale( const Locale& locale )
2436 {
2437 StringResourceImpl::removeLocale( locale );
2438 }
getUniqueNumericId()2439 sal_Int32 StringResourceWithStorageImpl::getUniqueNumericId( )
2440 {
2441 return StringResourceImpl::getUniqueNumericId();
2442 }
2443
2444 // XStringResourcePersistence
store()2445 void StringResourceWithStorageImpl::store()
2446 {
2447 ::osl::MutexGuard aGuard( getMutex() );
2448 implCheckReadOnly( "StringResourceWithStorageImpl::store(): Read only" );
2449
2450 bool bUsedForStore = true;
2451 bool bStoreAll = m_bStorageChanged;
2452 m_bStorageChanged = false;
2453 if( !m_bModified && !bStoreAll )
2454 return;
2455
2456 implStoreAtStorage( m_aNameBase, m_aComment, m_xStorage, bUsedForStore, bStoreAll );
2457 m_bModified = false;
2458 }
2459
isModified()2460 sal_Bool StringResourceWithStorageImpl::isModified( )
2461 {
2462 return StringResourcePersistenceImpl::isModified();
2463 }
setComment(const::rtl::OUString & Comment)2464 void StringResourceWithStorageImpl::setComment( const ::rtl::OUString& Comment )
2465 {
2466 StringResourcePersistenceImpl::setComment( Comment );
2467 }
storeToStorage(const Reference<XStorage> & Storage,const::rtl::OUString & NameBase,const::rtl::OUString & Comment)2468 void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage,
2469 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment )
2470 {
2471 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2472 }
storeToURL(const::rtl::OUString & URL,const::rtl::OUString & NameBase,const::rtl::OUString & Comment,const Reference<::com::sun::star::task::XInteractionHandler> & Handler)2473 void StringResourceWithStorageImpl::storeToURL( const ::rtl::OUString& URL,
2474 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment,
2475 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
2476 {
2477 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2478 }
exportBinary()2479 Sequence< ::sal_Int8 > StringResourceWithStorageImpl::exportBinary( )
2480 {
2481 return StringResourcePersistenceImpl::exportBinary();
2482 }
importBinary(const Sequence<::sal_Int8> & Data)2483 void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2484 {
2485 StringResourcePersistenceImpl::importBinary( Data );
2486 }
2487
2488 // -----------------------------------------------------------------------------
2489 // XStringResourceWithStorage
2490
storeAsStorage(const Reference<XStorage> & Storage)2491 void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage )
2492 {
2493 setStorage( Storage );
2494 store();
2495 }
2496
setStorage(const Reference<XStorage> & Storage)2497 void StringResourceWithStorageImpl::setStorage( const Reference< XStorage >& Storage )
2498 {
2499 ::osl::MutexGuard aGuard( getMutex() );
2500
2501 if( !Storage.is() )
2502 {
2503 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii
2504 ( "StringResourceWithStorageImpl::setStorage: invalid storage" );
2505 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2506 }
2507
2508 implLoadAllLocales();
2509
2510 m_xStorage = Storage;
2511 m_bStorageChanged = true;
2512 }
2513
2514
2515 // =============================================================================
2516 // Private helper methods
2517 // =============================================================================
2518
2519 // Scan locale properties files
implScanLocales(void)2520 void StringResourceWithStorageImpl::implScanLocales( void )
2521 {
2522 Reference< container::XNameAccess > xNameAccess( m_xStorage, UNO_QUERY );
2523 if( xNameAccess.is() )
2524 {
2525 Sequence< ::rtl::OUString > aContentSeq = xNameAccess->getElementNames();
2526 implScanLocaleNames( aContentSeq );
2527 }
2528
2529 implLoadAllLocales();
2530 }
2531
2532 // Loading
implLoadLocale(LocaleItem * pLocaleItem)2533 bool StringResourceWithStorageImpl::implLoadLocale( LocaleItem* pLocaleItem )
2534 {
2535 bool bSuccess = false;
2536 try
2537 {
2538 ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase );
2539 aStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".properties") );
2540
2541 Reference< io::XStream > xElementStream =
2542 m_xStorage->openStreamElement( aStreamName, ElementModes::READ );
2543
2544 if( xElementStream.is() )
2545 {
2546 Reference< io::XInputStream > xInputStream = xElementStream->getInputStream();
2547 if( xInputStream.is() )
2548 {
2549 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2550 xInputStream->closeInput();
2551 }
2552 }
2553 }
2554 catch( uno::Exception& )
2555 {}
2556
2557 return bSuccess;
2558 }
2559
2560
2561 // =============================================================================
2562 // StringResourceWithLocationImpl
2563 // =============================================================================
2564
2565 // component operations
getSupportedServiceNames_StringResourceWithLocationImpl()2566 static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceWithLocationImpl()
2567 {
2568 Sequence< ::rtl::OUString > names(1);
2569 names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResourceWithLocation") );
2570 return names;
2571 }
2572
getImplementationName_StringResourceWithLocationImpl()2573 static ::rtl::OUString getImplementationName_StringResourceWithLocationImpl()
2574 {
2575 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResourceWithLocation") );
2576 }
2577
create_StringResourceWithLocationImpl(Reference<XComponentContext> const & xContext)2578 static Reference< XInterface > SAL_CALL create_StringResourceWithLocationImpl(
2579 Reference< XComponentContext > const & xContext )
2580 SAL_THROW( () )
2581 {
2582 return static_cast< ::cppu::OWeakObject * >( new StringResourceWithLocationImpl( xContext ) );
2583 }
2584
2585 // -----------------------------------------------------------------------------
2586
StringResourceWithLocationImpl(const Reference<XComponentContext> & rxContext)2587 StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext )
2588 : StringResourceWithLocationImpl_BASE( rxContext )
2589 , m_bLocationChanged( false )
2590 {
2591 }
2592
2593 // -----------------------------------------------------------------------------
2594
~StringResourceWithLocationImpl()2595 StringResourceWithLocationImpl::~StringResourceWithLocationImpl()
2596 {
2597 }
2598
2599 // -----------------------------------------------------------------------------
2600 // XServiceInfo
2601 // -----------------------------------------------------------------------------
2602
getImplementationName()2603 ::rtl::OUString StringResourceWithLocationImpl::getImplementationName( )
2604 {
2605 return getImplementationName_StringResourceWithLocationImpl();
2606 }
2607
2608 // -----------------------------------------------------------------------------
2609
supportsService(const::rtl::OUString & rServiceName)2610 sal_Bool StringResourceWithLocationImpl::supportsService( const ::rtl::OUString& rServiceName )
2611 {
2612 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
2613 const ::rtl::OUString* pNames = aNames.getConstArray();
2614 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
2615 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
2616 ;
2617
2618 return pNames != pEnd;
2619 }
2620
2621 // -----------------------------------------------------------------------------
2622
getSupportedServiceNames()2623 Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getSupportedServiceNames( )
2624 {
2625 return getSupportedServiceNames_StringResourceWithLocationImpl();
2626 }
2627
2628 // -----------------------------------------------------------------------------
2629 // XInitialization
2630 // -----------------------------------------------------------------------------
2631
initialize(const Sequence<Any> & aArguments)2632 void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArguments )
2633 {
2634 ::osl::MutexGuard aGuard( getMutex() );
2635
2636 if ( aArguments.getLength() != 6 )
2637 {
2638 throw RuntimeException(
2639 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM
2640 ( "XInitialization::initialize: invalid number of arguments!" ) ),
2641 Reference< XInterface >() );
2642 }
2643
2644 bool bOk = (aArguments[0] >>= m_aLocation);
2645 sal_Int32 nLen = m_aLocation.getLength();
2646 if( bOk && nLen == 0 )
2647 {
2648 bOk = false;
2649 }
2650 else
2651 {
2652 if( m_aLocation.getStr()[nLen - 1] != '/' )
2653 m_aLocation += ::rtl::OUString::createFromAscii( "/" );
2654 }
2655
2656 if( !bOk )
2657 {
2658 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: invalid URL" );
2659 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2660 }
2661
2662
2663 bOk = (aArguments[5] >>= m_xInteractionHandler);
2664 if( !bOk )
2665 {
2666 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceWithStorageImpl::initialize: invalid type" );
2667 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 5 );
2668 }
2669
2670 implInitializeCommonParameters( aArguments );
2671 }
2672
2673 // -----------------------------------------------------------------------------
2674 // Forwarding calls to base class
2675
2676 // XModifyBroadcaster
addModifyListener(const Reference<XModifyListener> & aListener)2677 void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2678 {
2679 StringResourceImpl::addModifyListener( aListener );
2680 }
removeModifyListener(const Reference<XModifyListener> & aListener)2681 void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2682 {
2683 StringResourceImpl::removeModifyListener( aListener );
2684 }
2685
2686 // XStringResourceResolver
resolveString(const::rtl::OUString & ResourceID)2687 ::rtl::OUString StringResourceWithLocationImpl::resolveString( const ::rtl::OUString& ResourceID )
2688 {
2689 return StringResourceImpl::resolveString( ResourceID ) ;
2690 }
resolveStringForLocale(const::rtl::OUString & ResourceID,const Locale & locale)2691 ::rtl::OUString StringResourceWithLocationImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
2692 {
2693 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2694 }
hasEntryForId(const::rtl::OUString & ResourceID)2695 sal_Bool StringResourceWithLocationImpl::hasEntryForId( const ::rtl::OUString& ResourceID )
2696 {
2697 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2698 }
hasEntryForIdAndLocale(const::rtl::OUString & ResourceID,const Locale & locale)2699 sal_Bool StringResourceWithLocationImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID,
2700 const Locale& locale )
2701 {
2702 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2703 }
getResourceIDs()2704 Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getResourceIDs( )
2705 {
2706 return StringResourceImpl::getResourceIDs();
2707 }
getResourceIDsForLocale(const Locale & locale)2708 Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getResourceIDsForLocale
2709 ( const Locale& locale )
2710 {
2711 return StringResourceImpl::getResourceIDsForLocale( locale );
2712 }
getCurrentLocale()2713 Locale StringResourceWithLocationImpl::getCurrentLocale()
2714 {
2715 return StringResourceImpl::getCurrentLocale();
2716 }
getDefaultLocale()2717 Locale StringResourceWithLocationImpl::getDefaultLocale( )
2718 {
2719 return StringResourceImpl::getDefaultLocale();
2720 }
getLocales()2721 Sequence< Locale > StringResourceWithLocationImpl::getLocales( )
2722 {
2723 return StringResourceImpl::getLocales();
2724 }
2725
2726 // XStringResourceManager
isReadOnly()2727 sal_Bool StringResourceWithLocationImpl::isReadOnly()
2728 {
2729 return StringResourceImpl::isReadOnly();
2730 }
setCurrentLocale(const Locale & locale,sal_Bool FindClosestMatch)2731 void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2732 {
2733 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2734 }
setDefaultLocale(const Locale & locale)2735 void StringResourceWithLocationImpl::setDefaultLocale( const Locale& locale )
2736 {
2737 StringResourceImpl::setDefaultLocale( locale );
2738 }
setString(const::rtl::OUString & ResourceID,const::rtl::OUString & Str)2739 void StringResourceWithLocationImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str )
2740 {
2741 StringResourceImpl::setString( ResourceID, Str );
2742 }
setStringForLocale(const::rtl::OUString & ResourceID,const::rtl::OUString & Str,const Locale & locale)2743 void StringResourceWithLocationImpl::setStringForLocale
2744 ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale )
2745 {
2746 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2747 }
removeId(const::rtl::OUString & ResourceID)2748 void StringResourceWithLocationImpl::removeId( const ::rtl::OUString& ResourceID )
2749 {
2750 StringResourceImpl::removeId( ResourceID );
2751 }
removeIdForLocale(const::rtl::OUString & ResourceID,const Locale & locale)2752 void StringResourceWithLocationImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale )
2753 {
2754 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2755 }
newLocale(const Locale & locale)2756 void StringResourceWithLocationImpl::newLocale( const Locale& locale )
2757 {
2758 StringResourceImpl::newLocale( locale );
2759 }
removeLocale(const Locale & locale)2760 void StringResourceWithLocationImpl::removeLocale( const Locale& locale )
2761 {
2762 StringResourceImpl::removeLocale( locale );
2763 }
getUniqueNumericId()2764 sal_Int32 StringResourceWithLocationImpl::getUniqueNumericId( )
2765 {
2766 return StringResourceImpl::getUniqueNumericId();
2767 }
2768
2769 // XStringResourcePersistence
store()2770 void StringResourceWithLocationImpl::store()
2771 {
2772 ::osl::MutexGuard aGuard( getMutex() );
2773 implCheckReadOnly( "StringResourceWithLocationImpl::store(): Read only" );
2774
2775 bool bUsedForStore = true;
2776 bool bStoreAll = m_bLocationChanged;
2777 m_bLocationChanged = false;
2778 if( !m_bModified && !bStoreAll )
2779 return;
2780
2781 Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess();
2782 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2783 xFileAccess, bUsedForStore, bStoreAll );
2784 m_bModified = false;
2785 }
2786
isModified()2787 sal_Bool StringResourceWithLocationImpl::isModified( )
2788 {
2789 return StringResourcePersistenceImpl::isModified();
2790 }
setComment(const::rtl::OUString & Comment)2791 void StringResourceWithLocationImpl::setComment( const ::rtl::OUString& Comment )
2792 {
2793 StringResourcePersistenceImpl::setComment( Comment );
2794 }
storeToStorage(const Reference<XStorage> & Storage,const::rtl::OUString & NameBase,const::rtl::OUString & Comment)2795 void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage,
2796 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment )
2797 {
2798 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2799 }
storeToURL(const::rtl::OUString & URL,const::rtl::OUString & NameBase,const::rtl::OUString & Comment,const Reference<::com::sun::star::task::XInteractionHandler> & Handler)2800 void StringResourceWithLocationImpl::storeToURL( const ::rtl::OUString& URL,
2801 const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment,
2802 const Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
2803 {
2804 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2805 }
exportBinary()2806 Sequence< ::sal_Int8 > StringResourceWithLocationImpl::exportBinary( )
2807 {
2808 return StringResourcePersistenceImpl::exportBinary();
2809 }
importBinary(const Sequence<::sal_Int8> & Data)2810 void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2811 {
2812 StringResourcePersistenceImpl::importBinary( Data );
2813 }
2814
2815 // -----------------------------------------------------------------------------
2816 // XStringResourceWithLocation
2817
2818 // XStringResourceWithLocation
storeAsURL(const::rtl::OUString & URL)2819 void StringResourceWithLocationImpl::storeAsURL( const ::rtl::OUString& URL )
2820 {
2821 setURL( URL );
2822 store();
2823 }
2824
setURL(const::rtl::OUString & URL)2825 void StringResourceWithLocationImpl::setURL( const ::rtl::OUString& URL )
2826 {
2827 ::osl::MutexGuard aGuard( getMutex() );
2828 implCheckReadOnly( "StringResourceWithLocationImpl::setURL(): Read only" );
2829
2830 sal_Int32 nLen = URL.getLength();
2831 if( nLen == 0 )
2832 {
2833 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii
2834 ( "StringResourceWithLocationImpl::setURL: invalid URL" );
2835 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
2836 }
2837
2838 implLoadAllLocales();
2839
2840 // Delete files at old location
2841 bool bUsedForStore = false;
2842 bool bStoreAll = false;
2843 bool bKillAll = true;
2844 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2845 getFileAccess(), bUsedForStore, bStoreAll, bKillAll );
2846
2847 m_aLocation = URL;
2848 m_bLocationChanged = true;
2849 }
2850
2851
2852 // =============================================================================
2853 // Private helper methods
2854 // =============================================================================
2855
2856 // Scan locale properties files
implScanLocales(void)2857 void StringResourceWithLocationImpl::implScanLocales( void )
2858 {
2859 const Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess();
2860 if( xFileAccess.is() && xFileAccess->isFolder( m_aLocation ) )
2861 {
2862 Sequence< ::rtl::OUString > aContentSeq = xFileAccess->getFolderContents( m_aLocation, false );
2863 implScanLocaleNames( aContentSeq );
2864 }
2865 }
2866
2867 // Loading
implLoadLocale(LocaleItem * pLocaleItem)2868 bool StringResourceWithLocationImpl::implLoadLocale( LocaleItem* pLocaleItem )
2869 {
2870 bool bSuccess = false;
2871
2872 const Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess();
2873 if( xFileAccess.is() )
2874 {
2875 ::rtl::OUString aCompleteFileName =
2876 implGetPathForLocaleItem( pLocaleItem, m_aNameBase, m_aLocation );
2877
2878 Reference< io::XInputStream > xInputStream;
2879 try
2880 {
2881 xInputStream = xFileAccess->openFileRead( aCompleteFileName );
2882 }
2883 catch( Exception& )
2884 {}
2885 if( xInputStream.is() )
2886 {
2887 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2888 xInputStream->closeInput();
2889 }
2890 }
2891
2892 return bSuccess;
2893 }
2894
getFileAccess(void)2895 const Reference< ucb::XSimpleFileAccess > StringResourceWithLocationImpl::getFileAccess( void )
2896 {
2897 ::osl::MutexGuard aGuard( getMutex() );
2898
2899 if( !m_xSFI.is() )
2900 {
2901 Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory();
2902 m_xSFI = Reference< ucb::XSimpleFileAccess >( xMCF->createInstanceWithContext
2903 ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), m_xContext ), UNO_QUERY );
2904
2905 if( m_xSFI.is() && m_xInteractionHandler.is() )
2906 m_xSFI->setInteractionHandler( m_xInteractionHandler );
2907 }
2908 return m_xSFI;
2909 }
2910
2911
2912 // =============================================================================
2913 // component export operations
2914 // =============================================================================
2915
2916 static struct ::cppu::ImplementationEntry s_component_entries [] =
2917 {
2918 {
2919 create_StringResourceImpl, getImplementationName_StringResourceImpl,
2920 getSupportedServiceNames_StringResourceImpl,
2921 ::cppu::createSingleComponentFactory,
2922 0, 0
2923 },
2924 {
2925 create_StringResourceWithLocationImpl, getImplementationName_StringResourceWithLocationImpl,
2926 getSupportedServiceNames_StringResourceWithLocationImpl,
2927 ::cppu::createSingleComponentFactory,
2928 0, 0
2929 },
2930 {
2931 create_StringResourceWithStorageImpl, getImplementationName_StringResourceWithStorageImpl,
2932 getSupportedServiceNames_StringResourceWithStorageImpl,
2933 ::cppu::createSingleComponentFactory,
2934 0, 0
2935 },
2936 { 0, 0, 0, 0, 0, 0 }
2937 };
2938
2939
2940 //.........................................................................
2941 } // namespace dlgprov
2942 //.........................................................................
2943
2944
2945 // =============================================================================
2946 // component exports
2947 // =============================================================================
2948
2949 extern "C"
2950 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment ** ppEnv)2951 void SAL_CALL component_getImplementationEnvironment(
2952 const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
2953 {
2954 (void)ppEnv;
2955
2956 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
2957 }
2958
component_getFactory(const sal_Char * pImplName,lang::XMultiServiceFactory * pServiceManager,registry::XRegistryKey * pRegistryKey)2959 void * SAL_CALL component_getFactory(
2960 const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager,
2961 registry::XRegistryKey * pRegistryKey )
2962 {
2963 return ::cppu::component_getFactoryHelper(
2964 pImplName, pServiceManager, pRegistryKey, ::stringresource::s_component_entries );
2965 }
2966 }
2967