| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_scripting.hxx" |
| #include "stringresource.hxx" |
| #include <com/sun/star/io/XTextInputStream.hpp> |
| #include <com/sun/star/io/XTextOutputStream.hpp> |
| #include <com/sun/star/io/XActiveDataSink.hpp> |
| #include <com/sun/star/io/XActiveDataSource.hpp> |
| #include <com/sun/star/io/XStream.hpp> |
| #include <com/sun/star/io/XSeekable.hpp> |
| #include <com/sun/star/embed/ElementModes.hpp> |
| #include <com/sun/star/lang/XMultiComponentFactory.hpp> |
| #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ |
| #include <cppuhelper/implementationentry.hxx> |
| #endif |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/container/XNameAccess.hpp> |
| |
| |
| #include <rtl/ustrbuf.hxx> |
| #include <rtl/strbuf.hxx> |
| #include <tools/urlobj.hxx> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::ucb; |
| using namespace ::com::sun::star::util; |
| using namespace ::com::sun::star::embed; |
| using namespace ::com::sun::star::container; |
| |
| |
| //......................................................................... |
| namespace stringresource |
| { |
| //......................................................................... |
| |
| // ============================================================================= |
| // mutex |
| // ============================================================================= |
| |
| ::osl::Mutex& getMutex() |
| { |
| static ::osl::Mutex* s_pMutex = 0; |
| if ( !s_pMutex ) |
| { |
| ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); |
| if ( !s_pMutex ) |
| { |
| static ::osl::Mutex s_aMutex; |
| s_pMutex = &s_aMutex; |
| } |
| } |
| return *s_pMutex; |
| } |
| |
| |
| // ============================================================================= |
| // StringResourceImpl |
| // ============================================================================= |
| |
| // component operations |
| static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceImpl() |
| { |
| Sequence< ::rtl::OUString > names(1); |
| names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResource") ); |
| return names; |
| } |
| |
| static ::rtl::OUString getImplementationName_StringResourceImpl() |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResource") ); |
| } |
| |
| static Reference< XInterface > SAL_CALL create_StringResourceImpl( |
| Reference< XComponentContext > const & xContext ) |
| SAL_THROW( () ) |
| { |
| return static_cast< ::cppu::OWeakObject * >( new StringResourcePersistenceImpl( xContext ) ); |
| } |
| |
| |
| // ============================================================================= |
| |
| StringResourceImpl::StringResourceImpl( const Reference< XComponentContext >& rxContext ) |
| : m_xContext( rxContext ) |
| , m_pCurrentLocaleItem( NULL ) |
| , m_pDefaultLocaleItem( NULL ) |
| , m_bDefaultModified( false ) |
| , m_aListenerContainer( getMutex() ) |
| , m_bModified( false ) |
| , m_bReadOnly( false ) |
| , m_nNextUniqueNumericId( UNIQUE_NUMBER_NEEDS_INITIALISATION ) |
| { |
| } |
| |
| // ============================================================================= |
| |
| StringResourceImpl::~StringResourceImpl() |
| { |
| for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| delete pLocaleItem; |
| } |
| |
| for( LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin(); it != m_aDeletedLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| delete pLocaleItem; |
| } |
| } |
| |
| |
| // ============================================================================= |
| // XServiceInfo |
| |
| ::rtl::OUString StringResourceImpl::getImplementationName( ) throw (RuntimeException) |
| { |
| return getImplementationName_StringResourceImpl(); |
| } |
| |
| sal_Bool StringResourceImpl::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) |
| { |
| Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); |
| const ::rtl::OUString* pNames = aNames.getConstArray(); |
| const ::rtl::OUString* pEnd = pNames + aNames.getLength(); |
| for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) |
| ; |
| |
| return pNames != pEnd; |
| } |
| |
| Sequence< ::rtl::OUString > StringResourceImpl::getSupportedServiceNames( ) throw (RuntimeException) |
| { |
| return getSupportedServiceNames_StringResourceImpl(); |
| } |
| |
| |
| // ============================================================================= |
| // XModifyBroadcaster |
| |
| void StringResourceImpl::addModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| if( !aListener.is() ) |
| throw RuntimeException(); |
| |
| ::osl::MutexGuard aGuard( getMutex() ); |
| Reference< XInterface > xIface( aListener, UNO_QUERY ); |
| m_aListenerContainer.addInterface( xIface ); |
| } |
| |
| void StringResourceImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| if( !aListener.is() ) |
| throw RuntimeException(); |
| |
| ::osl::MutexGuard aGuard( getMutex() ); |
| Reference< XInterface > xIface( aListener, UNO_QUERY ); |
| m_aListenerContainer.removeInterface( xIface ); |
| } |
| |
| |
| // ============================================================================= |
| // XStringResourceResolver |
| |
| ::rtl::OUString StringResourceImpl::implResolveString |
| ( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem ) |
| throw (::com::sun::star::resource::MissingResourceException) |
| { |
| ::rtl::OUString aRetStr; |
| bool bSuccess = false; |
| if( pLocaleItem != NULL && loadLocale( pLocaleItem ) ) |
| { |
| IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID ); |
| if( !( it == pLocaleItem->m_aIdToStringMap.end() ) ) |
| { |
| aRetStr = (*it).second; |
| bSuccess = true; |
| } |
| } |
| if( !bSuccess ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: No entry for ResourceID: " ); |
| errorMsg.concat( ResourceID ); |
| throw ::com::sun::star::resource::MissingResourceException( errorMsg, Reference< XInterface >() ); |
| } |
| return aRetStr; |
| } |
| |
| ::rtl::OUString StringResourceImpl::resolveString( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| return implResolveString( ResourceID, m_pCurrentLocaleItem ); |
| } |
| |
| ::rtl::OUString StringResourceImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| LocaleItem* pLocaleItem = getItemForLocale( locale, false ); |
| return implResolveString( ResourceID, pLocaleItem ); |
| } |
| |
| sal_Bool StringResourceImpl::implHasEntryForId( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem ) |
| { |
| bool bSuccess = false; |
| if( pLocaleItem != NULL && loadLocale( pLocaleItem ) ) |
| { |
| IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID ); |
| if( !( it == pLocaleItem->m_aIdToStringMap.end() ) ) |
| bSuccess = true; |
| } |
| return bSuccess; |
| } |
| |
| sal_Bool StringResourceImpl::hasEntryForId( const ::rtl::OUString& ResourceID ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| return implHasEntryForId( ResourceID, m_pCurrentLocaleItem ); |
| } |
| |
| sal_Bool StringResourceImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID, |
| const Locale& locale ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| LocaleItem* pLocaleItem = getItemForLocale( locale, false ); |
| return implHasEntryForId( ResourceID, pLocaleItem ); |
| } |
| |
| Sequence< ::rtl::OUString > StringResourceImpl::implGetResourceIDs( LocaleItem* pLocaleItem ) |
| { |
| Sequence< ::rtl::OUString > aIDSeq( 0 ); |
| if( pLocaleItem && loadLocale( pLocaleItem ) ) |
| { |
| const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap; |
| sal_Int32 nResourceIDCount = rHashMap.size(); |
| aIDSeq.realloc( nResourceIDCount ); |
| ::rtl::OUString* pStrings = aIDSeq.getArray(); |
| |
| IdToStringMap::const_iterator it; |
| int iTarget = 0; |
| for( it = rHashMap.begin(); it != rHashMap.end(); it++ ) |
| { |
| ::rtl::OUString aStr = (*it).first; |
| pStrings[iTarget] = aStr; |
| iTarget++; |
| } |
| } |
| return aIDSeq; |
| } |
| |
| Sequence< ::rtl::OUString > StringResourceImpl::getResourceIDsForLocale |
| ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| LocaleItem* pLocaleItem = getItemForLocale( locale, false ); |
| return implGetResourceIDs( pLocaleItem ); |
| } |
| |
| Sequence< ::rtl::OUString > StringResourceImpl::getResourceIDs( ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| return implGetResourceIDs( m_pCurrentLocaleItem ); |
| } |
| |
| Locale StringResourceImpl::getCurrentLocale() |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| Locale aRetLocale; |
| if( m_pCurrentLocaleItem != NULL ) |
| aRetLocale = m_pCurrentLocaleItem->m_locale; |
| return aRetLocale; |
| } |
| |
| Locale StringResourceImpl::getDefaultLocale( ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| Locale aRetLocale; |
| if( m_pDefaultLocaleItem != NULL ) |
| aRetLocale = m_pDefaultLocaleItem->m_locale; |
| return aRetLocale; |
| } |
| |
| Sequence< Locale > StringResourceImpl::getLocales( ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| sal_Int32 nSize = m_aLocaleItemVector.size(); |
| Sequence< Locale > aLocalSeq( nSize ); |
| Locale* pLocales = aLocalSeq.getArray(); |
| int iTarget = 0; |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| pLocales[iTarget] = pLocaleItem->m_locale; |
| iTarget++; |
| } |
| return aLocalSeq; |
| } |
| |
| |
| // ============================================================================= |
| // XStringResourceManager |
| |
| void StringResourceImpl::implCheckReadOnly( const sal_Char* pExceptionMsg ) |
| throw (NoSupportException) |
| { |
| if( m_bReadOnly ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( pExceptionMsg ); |
| throw NoSupportException( errorMsg, Reference< XInterface >() ); |
| } |
| } |
| |
| sal_Bool StringResourceImpl::isReadOnly() |
| throw (RuntimeException) |
| { |
| return m_bReadOnly; |
| } |
| |
| void StringResourceImpl::implSetCurrentLocale( const Locale& locale, |
| sal_Bool FindClosestMatch, sal_Bool bUseDefaultIfNoMatch ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| LocaleItem* pLocaleItem = NULL; |
| if( FindClosestMatch ) |
| pLocaleItem = getClosestMatchItemForLocale( locale ); |
| else |
| pLocaleItem = getItemForLocale( locale, true ); |
| |
| if( pLocaleItem == NULL && bUseDefaultIfNoMatch ) |
| pLocaleItem = m_pDefaultLocaleItem; |
| |
| if( pLocaleItem != NULL ) |
| { |
| loadLocale( pLocaleItem ); |
| m_pCurrentLocaleItem = pLocaleItem; |
| |
| // Only notify without modifying |
| implNotifyListeners(); |
| } |
| } |
| |
| void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| sal_Bool bUseDefaultIfNoMatch = false; |
| implSetCurrentLocale( locale, FindClosestMatch, bUseDefaultIfNoMatch ); |
| } |
| |
| void StringResourceImpl::setDefaultLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException,NoSupportException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::setDefaultLocale(): Read only" ); |
| |
| LocaleItem* pLocaleItem = getItemForLocale( locale, true ); |
| if( pLocaleItem && pLocaleItem != m_pDefaultLocaleItem ) |
| { |
| if( m_pDefaultLocaleItem ) |
| { |
| LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale ); |
| m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem ); |
| } |
| |
| m_pDefaultLocaleItem = pLocaleItem; |
| m_bDefaultModified = true; |
| implModified(); |
| } |
| } |
| |
| void StringResourceImpl::implSetString( const ::rtl::OUString& ResourceID, |
| const ::rtl::OUString& Str, LocaleItem* pLocaleItem ) |
| { |
| if( pLocaleItem != NULL && loadLocale( pLocaleItem ) ) |
| { |
| IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap; |
| |
| IdToStringMap::iterator it = rHashMap.find( ResourceID ); |
| bool bNew = ( it == rHashMap.end() ); |
| if( bNew ) |
| { |
| IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap; |
| rIndexMap[ ResourceID ] = pLocaleItem->m_nNextIndex++; |
| implScanIdForNumber( ResourceID ); |
| } |
| rHashMap[ ResourceID ] = Str; |
| pLocaleItem->m_bModified = true; |
| implModified(); |
| } |
| } |
| |
| void StringResourceImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str ) |
| throw (NoSupportException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::setString(): Read only" ); |
| implSetString( ResourceID, Str, m_pCurrentLocaleItem ); |
| } |
| |
| void StringResourceImpl::setStringForLocale |
| ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale ) |
| throw (NoSupportException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::setStringForLocale(): Read only" ); |
| LocaleItem* pLocaleItem = getItemForLocale( locale, false ); |
| implSetString( ResourceID, Str, pLocaleItem ); |
| } |
| |
| void StringResourceImpl::implRemoveId( const ::rtl::OUString& ResourceID, LocaleItem* pLocaleItem ) |
| throw (::com::sun::star::resource::MissingResourceException) |
| { |
| if( pLocaleItem != NULL && loadLocale( pLocaleItem ) ) |
| { |
| IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap; |
| IdToStringMap::iterator it = rHashMap.find( ResourceID ); |
| if( it == rHashMap.end() ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: No entries for ResourceID: " ); |
| errorMsg.concat( ResourceID ); |
| throw ::com::sun::star::resource::MissingResourceException( errorMsg, Reference< XInterface >() ); |
| } |
| rHashMap.erase( it ); |
| pLocaleItem->m_bModified = true; |
| implModified(); |
| } |
| } |
| |
| void StringResourceImpl::removeId( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::removeId(): Read only" ); |
| implRemoveId( ResourceID, m_pCurrentLocaleItem ); |
| } |
| |
| void StringResourceImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::removeIdForLocale(): Read only" ); |
| LocaleItem* pLocaleItem = getItemForLocale( locale, false ); |
| implRemoveId( ResourceID, pLocaleItem ); |
| } |
| |
| void StringResourceImpl::newLocale( const Locale& locale ) |
| throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::newLocale(): Read only" ); |
| |
| if( getItemForLocale( locale, false ) != NULL ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: locale already exists" ); |
| throw ElementExistException( errorMsg, Reference< XInterface >() ); |
| } |
| |
| // TODO?: Check if locale is valid? How? |
| bool bValid = true; |
| if( bValid ) |
| { |
| LocaleItem* pLocaleItem = new LocaleItem( locale ); |
| m_aLocaleItemVector.push_back( pLocaleItem ); |
| pLocaleItem->m_bModified = true; |
| |
| // Copy strings from default locale |
| LocaleItem* pCopyFromItem = m_pDefaultLocaleItem; |
| if( pCopyFromItem == NULL ) |
| pCopyFromItem = m_pCurrentLocaleItem; |
| if( pCopyFromItem != NULL && loadLocale( pCopyFromItem ) ) |
| { |
| const IdToStringMap& rSourceMap = pCopyFromItem->m_aIdToStringMap; |
| IdToStringMap& rTargetMap = pLocaleItem->m_aIdToStringMap; |
| IdToStringMap::const_iterator it; |
| for( it = rSourceMap.begin(); it != rSourceMap.end(); it++ ) |
| { |
| ::rtl::OUString aId = (*it).first; |
| ::rtl::OUString aStr = (*it).second; |
| rTargetMap[ aId ] = aStr; |
| } |
| |
| const IdToIndexMap& rSourceIndexMap = pCopyFromItem->m_aIdToIndexMap; |
| IdToIndexMap& rTargetIndexMap = pLocaleItem->m_aIdToIndexMap; |
| IdToIndexMap::const_iterator it_index; |
| for( it_index = rSourceIndexMap.begin(); it_index != rSourceIndexMap.end(); it_index++ ) |
| { |
| ::rtl::OUString aId = (*it_index).first; |
| sal_Int32 nIndex = (*it_index).second; |
| rTargetIndexMap[ aId ] = nIndex; |
| } |
| pLocaleItem->m_nNextIndex = pCopyFromItem->m_nNextIndex; |
| } |
| |
| if( m_pCurrentLocaleItem == NULL ) |
| m_pCurrentLocaleItem = pLocaleItem; |
| |
| if( m_pDefaultLocaleItem == NULL ) |
| { |
| m_pDefaultLocaleItem = pLocaleItem; |
| m_bDefaultModified = true; |
| } |
| |
| implModified(); |
| } |
| else |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: Invalid locale" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| } |
| |
| void StringResourceImpl::removeLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" ); |
| |
| LocaleItem* pRemoveItem = getItemForLocale( locale, true ); |
| if( pRemoveItem ) |
| { |
| // Last locale? |
| sal_Int32 nLocaleCount = m_aLocaleItemVector.size(); |
| if( nLocaleCount > 1 ) |
| { |
| LocaleItem* pFallbackItem = NULL; |
| if( m_pCurrentLocaleItem == pRemoveItem || |
| m_pDefaultLocaleItem == pRemoveItem ) |
| { |
| for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != pRemoveItem ) |
| { |
| pFallbackItem = pLocaleItem; |
| break; |
| } |
| } |
| if( m_pCurrentLocaleItem == pRemoveItem ) |
| { |
| sal_Bool FindClosestMatch = false; |
| setCurrentLocale( pFallbackItem->m_locale, FindClosestMatch ); |
| } |
| if( m_pDefaultLocaleItem == pRemoveItem ) |
| { |
| setDefaultLocale( pFallbackItem->m_locale ); |
| } |
| } |
| } |
| for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem == pRemoveItem ) |
| { |
| // Remember locale item to delete file while storing |
| m_aDeletedLocaleItemVector.push_back( pLocaleItem ); |
| |
| // Last locale? |
| if( nLocaleCount == 1 ) |
| { |
| m_nNextUniqueNumericId = 0; |
| if( m_pDefaultLocaleItem ) |
| { |
| LocaleItem* pChangedDefaultLocaleItem = new LocaleItem( m_pDefaultLocaleItem->m_locale ); |
| m_aChangedDefaultLocaleVector.push_back( pChangedDefaultLocaleItem ); |
| } |
| m_pCurrentLocaleItem = NULL; |
| m_pDefaultLocaleItem = NULL; |
| } |
| |
| m_aLocaleItemVector.erase( it ); |
| |
| implModified(); |
| break; |
| } |
| } |
| } |
| } |
| |
| void StringResourceImpl::implScanIdForNumber( const ::rtl::OUString& ResourceID ) |
| { |
| const sal_Unicode* pSrc = ResourceID.getStr(); |
| sal_Int32 nLen = ResourceID.getLength(); |
| |
| sal_Int32 nNumber = 0; |
| for( sal_Int32 i = 0 ; i < nLen ; i++ ) |
| { |
| sal_Unicode c = pSrc[i]; |
| if( c >= '0' && c <= '9' ) |
| { |
| sal_uInt16 nDigitVal = c - '0'; |
| nNumber = 10*nNumber + nDigitVal; |
| } |
| else |
| break; |
| } |
| |
| if( m_nNextUniqueNumericId < nNumber + 1 ) |
| m_nNextUniqueNumericId = nNumber + 1; |
| } |
| |
| sal_Int32 StringResourceImpl::getUniqueNumericId( ) |
| throw (RuntimeException, NoSupportException) |
| { |
| if( m_nNextUniqueNumericId == UNIQUE_NUMBER_NEEDS_INITIALISATION ) |
| { |
| implLoadAllLocales(); |
| m_nNextUniqueNumericId = 0; |
| } |
| |
| if( m_nNextUniqueNumericId < UNIQUE_NUMBER_NEEDS_INITIALISATION ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "getUniqueNumericId: Extended sal_Int32 range" ); |
| throw NoSupportException( errorMsg, Reference< XInterface >() ); |
| } |
| return m_nNextUniqueNumericId; |
| } |
| |
| |
| // ============================================================================= |
| // Private helper methods |
| |
| LocaleItem* StringResourceImpl::getItemForLocale |
| ( const Locale& locale, sal_Bool bException ) |
| throw (::com::sun::star::lang::IllegalArgumentException) |
| { |
| LocaleItem* pRetItem = NULL; |
| |
| // Search for locale |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem ) |
| { |
| Locale& cmp_locale = pLocaleItem->m_locale; |
| if( cmp_locale.Language == locale.Language && |
| cmp_locale.Country == locale.Country && |
| cmp_locale.Variant == locale.Variant ) |
| { |
| pRetItem = pLocaleItem; |
| break; |
| } |
| } |
| } |
| |
| if( pRetItem == NULL && bException ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceImpl: Invalid locale" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| return pRetItem; |
| } |
| |
| // Returns the LocalItem for a given locale, if it exists, otherwise NULL |
| // This method performes a closest match search, at least the language must match |
| LocaleItem* StringResourceImpl::getClosestMatchItemForLocale( const Locale& locale ) |
| { |
| LocaleItem* pRetItem = NULL; |
| |
| // Search for locale |
| for( sal_Int32 iPass = 0 ; iPass <= 2 ; ++iPass ) |
| { |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem ) |
| { |
| Locale& cmp_locale = pLocaleItem->m_locale; |
| if( cmp_locale.Language == locale.Language && |
| (iPass > 1 || cmp_locale.Country == locale.Country) && |
| (iPass > 0 || cmp_locale.Variant == locale.Variant) ) |
| { |
| pRetItem = pLocaleItem; |
| break; |
| } |
| } |
| } |
| if( pRetItem ) |
| break; |
| } |
| |
| return pRetItem; |
| } |
| |
| void StringResourceImpl::implModified( void ) |
| { |
| m_bModified = true; |
| implNotifyListeners(); |
| } |
| |
| void StringResourceImpl::implNotifyListeners( void ) |
| { |
| EventObject aEvent; |
| aEvent.Source = static_cast< XInterface* >( (OWeakObject*)this ); |
| |
| ::cppu::OInterfaceIteratorHelper it( m_aListenerContainer ); |
| while( it.hasMoreElements() ) |
| { |
| Reference< XInterface > xIface = it.next(); |
| Reference< XModifyListener > xListener( xIface, UNO_QUERY ); |
| try |
| { |
| xListener->modified( aEvent ); |
| } |
| catch(RuntimeException&) |
| { |
| it.remove(); |
| } |
| } |
| } |
| |
| |
| // ============================================================================= |
| // Loading |
| |
| bool StringResourceImpl::loadLocale( LocaleItem* pLocaleItem ) |
| { |
| // Base implementation has nothing to load |
| (void)pLocaleItem; |
| return true; |
| } |
| |
| void StringResourceImpl::implLoadAllLocales( void ) |
| { |
| // Base implementation has nothing to load |
| } |
| |
| |
| Reference< XMultiComponentFactory > StringResourceImpl::getMultiComponentFactory( void ) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| if( !m_xMCF.is() ) |
| { |
| Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); |
| if( !xSMgr.is() ) |
| { |
| throw RuntimeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringResourceImpl::getMultiComponentFactory: Couldn't instantiate MultiComponentFactory" ) ), |
| Reference< XInterface >() ); |
| } |
| m_xMCF = xSMgr; |
| } |
| return m_xMCF; |
| } |
| |
| |
| // ============================================================================= |
| // StringResourcePersistenceImpl |
| // ============================================================================= |
| |
| StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext ) |
| : StringResourcePersistenceImpl_BASE( rxContext ) |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| StringResourcePersistenceImpl::~StringResourcePersistenceImpl() |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XServiceInfo |
| // ----------------------------------------------------------------------------- |
| |
| ::rtl::OUString StringResourcePersistenceImpl::getImplementationName( ) |
| throw (RuntimeException) |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM |
| ( "com.sun.star.comp.scripting.StringResourceWithLocation") ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_Bool StringResourcePersistenceImpl::supportsService( const ::rtl::OUString& rServiceName ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::supportsService( rServiceName ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getSupportedServiceNames( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getSupportedServiceNames(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XInitialization base functionality for derived classes |
| // ----------------------------------------------------------------------------- |
| |
| static ::rtl::OUString aNameBaseDefaultStr = ::rtl::OUString::createFromAscii( "strings" ); |
| |
| void StringResourcePersistenceImpl::implInitializeCommonParameters |
| ( const Sequence< Any >& aArguments ) |
| throw (Exception, RuntimeException) |
| { |
| bool bReadOnlyOk = (aArguments[1] >>= m_bReadOnly); |
| if( !bReadOnlyOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected ReadOnly flag" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 1 ); |
| } |
| |
| com::sun::star::lang::Locale aCurrentLocale; |
| bool bLocaleOk = (aArguments[2] >>= aCurrentLocale); |
| if( !bLocaleOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected Locale" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 2 ); |
| } |
| |
| bool bNameBaseOk = (aArguments[3] >>= m_aNameBase); |
| if( !bNameBaseOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected NameBase string" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 3 ); |
| } |
| if( m_aNameBase.getLength() == 0 ) |
| m_aNameBase = aNameBaseDefaultStr; |
| |
| bool bCommentOk = (aArguments[4] >>= m_aComment); |
| if( !bCommentOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: Expected Comment string" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 4 ); |
| } |
| |
| implScanLocales(); |
| |
| sal_Bool FindClosestMatch = true; |
| sal_Bool bUseDefaultIfNoMatch = true; |
| implSetCurrentLocale( aCurrentLocale, FindClosestMatch, bUseDefaultIfNoMatch ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // Forwarding calls to base class |
| |
| // XModifyBroadcaster |
| void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::addModifyListener( aListener ); |
| } |
| void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::removeModifyListener( aListener ); |
| } |
| |
| // XStringResourceResolver |
| ::rtl::OUString StringResourcePersistenceImpl::resolveString( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveString( ResourceID ) ; |
| } |
| ::rtl::OUString StringResourcePersistenceImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); |
| } |
| sal_Bool StringResourcePersistenceImpl::hasEntryForId( const ::rtl::OUString& ResourceID ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForId( ResourceID ) ; |
| } |
| sal_Bool StringResourcePersistenceImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID, |
| const Locale& locale ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); |
| } |
| Locale StringResourcePersistenceImpl::getCurrentLocale() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getCurrentLocale(); |
| } |
| Locale StringResourcePersistenceImpl::getDefaultLocale( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getDefaultLocale(); |
| } |
| Sequence< Locale > StringResourcePersistenceImpl::getLocales( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getLocales(); |
| } |
| |
| // XStringResourceManager |
| sal_Bool StringResourcePersistenceImpl::isReadOnly() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::isReadOnly(); |
| } |
| void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); |
| } |
| void StringResourcePersistenceImpl::setDefaultLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException,NoSupportException) |
| { |
| StringResourceImpl::setDefaultLocale( locale ); |
| } |
| Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getResourceIDs( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDs(); |
| } |
| void StringResourcePersistenceImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setString( ResourceID, Str ); |
| } |
| void StringResourcePersistenceImpl::setStringForLocale |
| ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); |
| } |
| Sequence< ::rtl::OUString > StringResourcePersistenceImpl::getResourceIDsForLocale |
| ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDsForLocale( locale ); |
| } |
| void StringResourcePersistenceImpl::removeId( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeId( ResourceID ); |
| } |
| void StringResourcePersistenceImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeIdForLocale( ResourceID, locale ); |
| } |
| void StringResourcePersistenceImpl::newLocale( const Locale& locale ) |
| throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::newLocale( locale ); |
| } |
| void StringResourcePersistenceImpl::removeLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeLocale( locale ); |
| } |
| sal_Int32 StringResourcePersistenceImpl::getUniqueNumericId( ) |
| throw (RuntimeException, NoSupportException) |
| { |
| return StringResourceImpl::getUniqueNumericId(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XStringResourcePersistence |
| |
| void StringResourcePersistenceImpl::store() |
| throw (NoSupportException, Exception, RuntimeException) |
| { |
| } |
| |
| sal_Bool StringResourcePersistenceImpl::isModified( ) |
| throw (RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| return m_bModified; |
| } |
| |
| void StringResourcePersistenceImpl::setComment( const ::rtl::OUString& Comment ) |
| throw (::com::sun::star::uno::RuntimeException) |
| { |
| m_aComment = Comment; |
| } |
| |
| void StringResourcePersistenceImpl::storeToStorage( const Reference< XStorage >& Storage, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment ) |
| throw (Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| bool bUsedForStore = false; |
| bool bStoreAll = true; |
| implStoreAtStorage( NameBase, Comment, Storage, bUsedForStore, bStoreAll ); |
| } |
| |
| void StringResourcePersistenceImpl::implStoreAtStorage |
| ( |
| const ::rtl::OUString& aNameBase, |
| const ::rtl::OUString& aComment, |
| const Reference< ::com::sun::star::embed::XStorage >& Storage, |
| bool bUsedForStore, |
| bool bStoreAll |
| ) |
| throw (Exception, RuntimeException) |
| { |
| // Delete files for deleted locales |
| if( bUsedForStore ) |
| { |
| while( m_aDeletedLocaleItemVector.size() > 0 ) |
| { |
| LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin(); |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL ) |
| { |
| ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase ); |
| aStreamName += ::rtl::OUString::createFromAscii( ".properties" ); |
| |
| try |
| { |
| Storage->removeElement( aStreamName ); |
| } |
| catch( Exception& ) |
| {} |
| |
| m_aDeletedLocaleItemVector.erase( it ); |
| delete pLocaleItem; |
| } |
| } |
| } |
| |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL && (bStoreAll || pLocaleItem->m_bModified) && |
| loadLocale( pLocaleItem ) ) |
| { |
| ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase ); |
| aStreamName += ::rtl::OUString::createFromAscii( ".properties" ); |
| |
| Reference< io::XStream > xElementStream = |
| Storage->openStreamElement( aStreamName, ElementModes::READWRITE ); |
| |
| ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "MediaType" ); |
| ::rtl::OUString aMime = ::rtl::OUString::createFromAscii( "text/plain" ); |
| |
| uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY ); |
| OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!\n" ); |
| if ( xProps.is() ) |
| { |
| xProps->setPropertyValue( aPropName, uno::makeAny( aMime ) ); |
| |
| aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ); |
| xProps->setPropertyValue( aPropName, uno::makeAny( sal_True ) ); |
| } |
| |
| Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream(); |
| if( xOutputStream.is() ) |
| implWritePropertiesFile( pLocaleItem, xOutputStream, aComment ); |
| xOutputStream->closeOutput(); |
| |
| if( bUsedForStore ) |
| pLocaleItem->m_bModified = false; |
| } |
| } |
| |
| // Delete files for changed defaults |
| if( bUsedForStore ) |
| { |
| for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin(); |
| it != m_aChangedDefaultLocaleVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL ) |
| { |
| ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase ); |
| aStreamName += ::rtl::OUString::createFromAscii( ".default" ); |
| |
| try |
| { |
| Storage->removeElement( aStreamName ); |
| } |
| catch( Exception& ) |
| {} |
| |
| delete pLocaleItem; |
| } |
| } |
| m_aChangedDefaultLocaleVector.clear(); |
| } |
| |
| // Default locale |
| if( m_pDefaultLocaleItem != NULL && (bStoreAll || m_bDefaultModified) ) |
| { |
| ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( m_pDefaultLocaleItem, aNameBase ); |
| aStreamName += ::rtl::OUString::createFromAscii( ".default" ); |
| |
| Reference< io::XStream > xElementStream = |
| Storage->openStreamElement( aStreamName, ElementModes::READWRITE ); |
| |
| ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "MediaType" ); |
| ::rtl::OUString aMime = ::rtl::OUString::createFromAscii( "text/plain" ); |
| |
| // Only create stream without content |
| Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream(); |
| xOutputStream->closeOutput(); |
| |
| if( bUsedForStore ) |
| m_bDefaultModified = false; |
| } |
| } |
| |
| void StringResourcePersistenceImpl::storeToURL( const ::rtl::OUString& URL, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment, |
| const Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) |
| throw (Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| bool bUsedForStore = false; |
| bool bStoreAll = true; |
| |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| Reference< ucb::XSimpleFileAccess > xFileAccess; |
| xFileAccess = Reference< ucb::XSimpleFileAccess >( xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), |
| m_xContext ), UNO_QUERY ); |
| if( xFileAccess.is() && Handler.is() ) |
| xFileAccess->setInteractionHandler( Handler ); |
| |
| implStoreAtLocation( URL, NameBase, Comment, xFileAccess, bUsedForStore, bStoreAll ); |
| } |
| |
| void StringResourcePersistenceImpl::implKillRemovedLocaleFiles |
| ( |
| const ::rtl::OUString& Location, |
| const ::rtl::OUString& aNameBase, |
| const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xFileAccess |
| ) |
| throw (Exception, RuntimeException) |
| { |
| // Delete files for deleted locales |
| while( m_aDeletedLocaleItemVector.size() > 0 ) |
| { |
| LocaleItemVectorIt it = m_aDeletedLocaleItemVector.begin(); |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL ) |
| { |
| ::rtl::OUString aCompleteFileName = |
| implGetPathForLocaleItem( pLocaleItem, aNameBase, Location ); |
| if( xFileAccess->exists( aCompleteFileName ) ) |
| xFileAccess->kill( aCompleteFileName ); |
| |
| m_aDeletedLocaleItemVector.erase( it ); |
| delete pLocaleItem; |
| } |
| } |
| } |
| |
| void StringResourcePersistenceImpl::implKillChangedDefaultFiles |
| ( |
| const ::rtl::OUString& Location, |
| const ::rtl::OUString& aNameBase, |
| const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess >& xFileAccess |
| ) |
| throw (Exception, RuntimeException) |
| { |
| // Delete files for changed defaults |
| for( LocaleItemVectorIt it = m_aChangedDefaultLocaleVector.begin(); |
| it != m_aChangedDefaultLocaleVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL ) |
| { |
| ::rtl::OUString aCompleteFileName = |
| implGetPathForLocaleItem( pLocaleItem, aNameBase, Location, true ); |
| if( xFileAccess->exists( aCompleteFileName ) ) |
| xFileAccess->kill( aCompleteFileName ); |
| |
| delete pLocaleItem; |
| } |
| } |
| m_aChangedDefaultLocaleVector.clear(); |
| } |
| |
| void StringResourcePersistenceImpl::implStoreAtLocation |
| ( |
| const ::rtl::OUString& Location, |
| const ::rtl::OUString& aNameBase, |
| const ::rtl::OUString& aComment, |
| const Reference< ucb::XSimpleFileAccess >& xFileAccess, |
| bool bUsedForStore, |
| bool bStoreAll, |
| bool bKillAll |
| ) |
| throw (Exception, RuntimeException) |
| { |
| // Delete files for deleted locales |
| if( bUsedForStore || bKillAll ) |
| implKillRemovedLocaleFiles( Location, aNameBase, xFileAccess ); |
| |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL && (bStoreAll || bKillAll || pLocaleItem->m_bModified) && |
| loadLocale( pLocaleItem ) ) |
| { |
| ::rtl::OUString aCompleteFileName = |
| implGetPathForLocaleItem( pLocaleItem, aNameBase, Location ); |
| if( xFileAccess->exists( aCompleteFileName ) ) |
| xFileAccess->kill( aCompleteFileName ); |
| |
| if( !bKillAll ) |
| { |
| // Create Output stream |
| Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName ); |
| if( xOutputStream.is() ) |
| { |
| implWritePropertiesFile( pLocaleItem, xOutputStream, aComment ); |
| xOutputStream->closeOutput(); |
| } |
| if( bUsedForStore ) |
| pLocaleItem->m_bModified = false; |
| } |
| } |
| } |
| |
| // Delete files for changed defaults |
| if( bUsedForStore || bKillAll ) |
| implKillChangedDefaultFiles( Location, aNameBase, xFileAccess ); |
| |
| // Default locale |
| if( m_pDefaultLocaleItem != NULL && (bStoreAll || bKillAll || m_bDefaultModified) ) |
| { |
| ::rtl::OUString aCompleteFileName = |
| implGetPathForLocaleItem( m_pDefaultLocaleItem, aNameBase, Location, true ); |
| if( xFileAccess->exists( aCompleteFileName ) ) |
| xFileAccess->kill( aCompleteFileName ); |
| |
| if( !bKillAll ) |
| { |
| // Create Output stream |
| Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName ); |
| if( xOutputStream.is() ) |
| xOutputStream->closeOutput(); |
| |
| if( bUsedForStore ) |
| m_bDefaultModified = false; |
| } |
| } |
| } |
| |
| |
| // ----------------------------------------------------------------------------- |
| // BinaryOutput, helper class for exportBinary |
| |
| class BinaryOutput |
| { |
| Reference< XMultiComponentFactory > m_xMCF; |
| Reference< XComponentContext > m_xContext; |
| Reference< XInterface > m_xTempFile; |
| Reference< io::XOutputStream > m_xOutputStream; |
| |
| public: |
| BinaryOutput( Reference< XMultiComponentFactory > xMCF, |
| Reference< XComponentContext > xContext ); |
| |
| Reference< io::XOutputStream > getOutputStream( void ) |
| { return m_xOutputStream; } |
| |
| Sequence< ::sal_Int8 > closeAndGetData( void ); |
| |
| // Template to be used with sal_Int16 and sal_Unicode |
| template< class T > |
| void write16BitInt( T n ); |
| void writeInt16( sal_Int16 n ) |
| { write16BitInt( n ); } |
| void writeUnicodeChar( sal_Unicode n ) |
| { write16BitInt( n ); } |
| void writeInt32( sal_Int32 n ); |
| void writeString( const ::rtl::OUString& aStr ); |
| }; |
| |
| BinaryOutput::BinaryOutput( Reference< XMultiComponentFactory > xMCF, |
| Reference< XComponentContext > xContext ) |
| : m_xMCF( xMCF ) |
| , m_xContext( xContext ) |
| { |
| m_xTempFile = m_xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ), m_xContext ); |
| if( m_xTempFile.is() ) |
| m_xOutputStream = Reference< io::XOutputStream >( m_xTempFile, UNO_QUERY ); |
| } |
| |
| template< class T > |
| void BinaryOutput::write16BitInt( T n ) |
| { |
| if( !m_xOutputStream.is() ) |
| return; |
| |
| Sequence< sal_Int8 > aSeq( 2 ); |
| sal_Int8* p = aSeq.getArray(); |
| |
| sal_Int8 nLow = sal_Int8( n & 0xff ); |
| sal_Int8 nHigh = sal_Int8( n >> 8 ); |
| |
| p[0] = nLow; |
| p[1] = nHigh; |
| m_xOutputStream->writeBytes( aSeq ); |
| } |
| |
| void BinaryOutput::writeInt32( sal_Int32 n ) |
| { |
| if( !m_xOutputStream.is() ) |
| return; |
| |
| Sequence< sal_Int8 > aSeq( 4 ); |
| sal_Int8* p = aSeq.getArray(); |
| |
| for( sal_Int16 i = 0 ; i < 4 ; i++ ) |
| { |
| p[i] = sal_Int8( n & 0xff ); |
| n >>= 8; |
| } |
| m_xOutputStream->writeBytes( aSeq ); |
| } |
| |
| void BinaryOutput::writeString( const ::rtl::OUString& aStr ) |
| { |
| sal_Int32 nLen = aStr.getLength(); |
| const sal_Unicode* pStr = aStr.getStr(); |
| |
| for( sal_Int32 i = 0 ; i < nLen ; i++ ) |
| writeUnicodeChar( pStr[i] ); |
| |
| writeUnicodeChar( 0 ); |
| } |
| |
| Sequence< ::sal_Int8 > BinaryOutput::closeAndGetData( void ) |
| { |
| Sequence< ::sal_Int8 > aRetSeq; |
| if( !m_xOutputStream.is() ) |
| return aRetSeq; |
| |
| m_xOutputStream->closeOutput(); |
| |
| Reference< io::XSeekable> xSeekable( m_xTempFile, UNO_QUERY ); |
| if( !xSeekable.is() ) |
| return aRetSeq; |
| |
| sal_Int32 nSize = (sal_Int32)xSeekable->getPosition(); |
| |
| Reference< io::XInputStream> xInputStream( m_xTempFile, UNO_QUERY ); |
| if( !xInputStream.is() ) |
| return aRetSeq; |
| |
| xSeekable->seek( 0 ); |
| sal_Int32 nRead = xInputStream->readBytes( aRetSeq, nSize ); |
| (void)nRead; |
| OSL_ENSURE( nRead == nSize, "BinaryOutput::closeAndGetData: nRead != nSize" ); |
| |
| return aRetSeq; |
| } |
| |
| |
| // Binary format: |
| |
| // Header |
| // Byte Content |
| // 0 + 1 sal_Int16: Version, currently 0, low byte first |
| // 2 + 3 sal_Int16: Locale count = n, low byte first |
| // 4 + 5 sal_Int16: Default Locale position in Locale list, == n if none |
| // 6 - 7 sal_Int32: Start index locale block 0, lowest byte first |
| // (n-1) * sal_Int32: Start index locale block 1 to n, lowest byte first |
| // 6 + 4*n sal_Int32: "Start index" non existing locale block n+1, |
| // marks the first invalid index, kind of EOF |
| |
| // Locale block |
| // All strings are stored as 2-Byte-0 terminated sequence |
| // of 16 bit Unicode characters, each with low byte first |
| // Empty strings only contain the 2-Byte-0 |
| |
| // Members of com.sun.star.lang.Locale |
| // with l1 = Locale.Language.getLength() |
| // with l2 = Locale.Country.getLength() |
| // with l3 = Locale.Variant.getLength() |
| // pos0 = 0 Locale.Language |
| // pos1 = 2 * (l1 + 1) Locale.Country |
| // pos2 = pos1 + 2 * (l2 + 1) Locale.Variant |
| // pos3 = pos2 + 2 * (l3 + 1) |
| // pos3 Properties file written by implWritePropertiesFile |
| |
| Sequence< sal_Int8 > StringResourcePersistenceImpl::exportBinary( ) |
| throw (RuntimeException) |
| { |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| BinaryOutput aOut( xMCF, m_xContext ); |
| |
| sal_Int32 nLocaleCount = m_aLocaleItemVector.size(); |
| Sequence< sal_Int8 >* pLocaleDataSeq = new Sequence< sal_Int8 >[ nLocaleCount ]; |
| |
| sal_Int32 iLocale = 0; |
| sal_Int32 iDefault = 0; |
| for( LocaleItemVectorConstIt it = m_aLocaleItemVector.begin(); |
| it != m_aLocaleItemVector.end(); it++,iLocale++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL && loadLocale( pLocaleItem ) ) |
| { |
| if( m_pDefaultLocaleItem == pLocaleItem ) |
| iDefault = iLocale; |
| |
| BinaryOutput aLocaleOut( m_xMCF, m_xContext ); |
| implWriteLocaleBinary( pLocaleItem, aLocaleOut ); |
| |
| pLocaleDataSeq[iLocale] = aLocaleOut.closeAndGetData(); |
| } |
| } |
| |
| // Write header |
| sal_Int16 nVersion = 0; |
| sal_Int16 nLocaleCount16 = (sal_Int16)nLocaleCount; |
| sal_Int16 iDefault16 = (sal_Int16)iDefault; |
| aOut.writeInt16( nVersion ); |
| aOut.writeInt16( nLocaleCount16 ); |
| aOut.writeInt16( iDefault16 ); |
| |
| // Write data positions |
| sal_Int32 nDataPos = 6 + 4 * (nLocaleCount + 1); |
| for( iLocale = 0; iLocale < nLocaleCount; iLocale++ ) |
| { |
| aOut.writeInt32( nDataPos ); |
| |
| Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale]; |
| sal_Int32 nSeqLen = rSeq.getLength(); |
| nDataPos += nSeqLen; |
| } |
| // Write final position |
| aOut.writeInt32( nDataPos ); |
| |
| // Write data |
| Reference< io::XOutputStream > xOutputStream = aOut.getOutputStream(); |
| if( xOutputStream.is() ) |
| { |
| for( iLocale = 0; iLocale < nLocaleCount; iLocale++ ) |
| { |
| Sequence< sal_Int8 >& rSeq = pLocaleDataSeq[iLocale]; |
| xOutputStream->writeBytes( rSeq ); |
| } |
| } |
| |
| delete[] pLocaleDataSeq; |
| |
| Sequence< sal_Int8 > aRetSeq = aOut.closeAndGetData(); |
| return aRetSeq; |
| } |
| |
| void StringResourcePersistenceImpl::implWriteLocaleBinary |
| ( LocaleItem* pLocaleItem, BinaryOutput& rOut ) |
| { |
| Reference< io::XOutputStream > xOutputStream = rOut.getOutputStream(); |
| if( !xOutputStream.is() ) |
| return; |
| |
| Locale& rLocale = pLocaleItem->m_locale; |
| rOut.writeString( rLocale.Language ); |
| rOut.writeString( rLocale.Country ); |
| rOut.writeString( rLocale.Variant ); |
| implWritePropertiesFile( pLocaleItem, xOutputStream, m_aComment ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // BinaryOutput, helper class for exportBinary |
| |
| class BinaryInput |
| { |
| Sequence< sal_Int8 > m_aData; |
| Reference< XMultiComponentFactory > m_xMCF; |
| Reference< XComponentContext > m_xContext; |
| |
| const sal_Int8* m_pData; |
| sal_Int32 m_nCurPos; |
| sal_Int32 m_nSize; |
| |
| public: |
| BinaryInput( Sequence< ::sal_Int8 > aData, Reference< XMultiComponentFactory > xMCF, |
| Reference< XComponentContext > xContext ); |
| |
| Reference< io::XInputStream > getInputStreamForSection( sal_Int32 nSize ); |
| |
| void seek( sal_Int32 nPos ); |
| sal_Int32 getPosition( void ) |
| { return m_nCurPos; } |
| |
| sal_Int16 readInt16( void ); |
| sal_Int32 readInt32( void ); |
| sal_Unicode readUnicodeChar( void ); |
| ::rtl::OUString readString( void ); |
| }; |
| |
| BinaryInput::BinaryInput( Sequence< ::sal_Int8 > aData, Reference< XMultiComponentFactory > xMCF, |
| Reference< XComponentContext > xContext ) |
| : m_aData( aData ) |
| , m_xMCF( xMCF ) |
| , m_xContext( xContext ) |
| { |
| m_pData = m_aData.getConstArray(); |
| m_nCurPos = 0; |
| m_nSize = m_aData.getLength(); |
| } |
| |
| Reference< io::XInputStream > BinaryInput::getInputStreamForSection( sal_Int32 nSize ) |
| { |
| Reference< io::XInputStream > xIn; |
| if( m_nCurPos + nSize <= m_nSize ) |
| { |
| Reference< io::XOutputStream > xTempOut( m_xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ), m_xContext ), UNO_QUERY ); |
| if( xTempOut.is() ) |
| { |
| Sequence< sal_Int8 > aSection( m_pData + m_nCurPos, nSize ); |
| xTempOut->writeBytes( aSection ); |
| |
| Reference< io::XSeekable> xSeekable( xTempOut, UNO_QUERY ); |
| if( xSeekable.is() ) |
| xSeekable->seek( 0 ); |
| |
| xIn = Reference< io::XInputStream>( xTempOut, UNO_QUERY ); |
| } |
| } |
| else |
| OSL_ENSURE( false, "BinaryInput::getInputStreamForSection(): Read past end" ); |
| |
| return xIn; |
| } |
| |
| void BinaryInput::seek( sal_Int32 nPos ) |
| { |
| if( nPos <= m_nSize ) |
| m_nCurPos = nPos; |
| else |
| OSL_ENSURE( false, "BinaryInput::seek(): Position past end" ); |
| } |
| |
| |
| sal_Int16 BinaryInput::readInt16( void ) |
| { |
| sal_Int16 nRet = 0; |
| if( m_nCurPos + 2 <= m_nSize ) |
| { |
| nRet = nRet + sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) ); |
| nRet += 256 * sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) ); |
| } |
| else |
| OSL_ENSURE( false, "BinaryInput::readInt16(): Read past end" ); |
| |
| return nRet; |
| } |
| |
| sal_Int32 BinaryInput::readInt32( void ) |
| { |
| sal_Int32 nRet = 0; |
| if( m_nCurPos + 4 <= m_nSize ) |
| { |
| sal_Int32 nFactor = 1; |
| for( sal_Int16 i = 0; i < 4; i++ ) |
| { |
| nRet += sal_uInt8( m_pData[m_nCurPos++] ) * nFactor; |
| nFactor *= 256; |
| } |
| } |
| else |
| OSL_ENSURE( false, "BinaryInput::readInt32(): Read past end" ); |
| |
| return nRet; |
| } |
| |
| sal_Unicode BinaryInput::readUnicodeChar( void ) |
| { |
| sal_uInt16 nRet = 0; |
| if( m_nCurPos + 2 <= m_nSize ) |
| { |
| nRet = nRet + sal_uInt8( m_pData[m_nCurPos++] ); |
| nRet += 256 * sal_uInt8( m_pData[m_nCurPos++] ); |
| } |
| else |
| OSL_ENSURE( false, "BinaryInput::readUnicodeChar(): Read past end" ); |
| |
| sal_Unicode cRet = nRet; |
| return cRet; |
| } |
| |
| ::rtl::OUString BinaryInput::readString( void ) |
| { |
| ::rtl::OUStringBuffer aBuf; |
| sal_Unicode c; |
| do |
| { |
| c = readUnicodeChar(); |
| if( c != 0 ) |
| aBuf.append( c ); |
| } |
| while( c != 0 ); |
| |
| ::rtl::OUString aRetStr = aBuf.makeStringAndClear(); |
| return aRetStr; |
| } |
| |
| void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& Data ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| // Init: Remove all locales |
| sal_Int32 nOldLocaleCount = 0; |
| do |
| { |
| Sequence< Locale > aLocaleSeq = getLocales(); |
| nOldLocaleCount = aLocaleSeq.getLength(); |
| if( nOldLocaleCount > 0 ) |
| { |
| Locale aLocale = aLocaleSeq[0]; |
| removeLocale( aLocale ); |
| } |
| } |
| while( nOldLocaleCount > 0 ); |
| |
| // Import data |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| BinaryInput aIn( Data, xMCF, m_xContext ); |
| |
| sal_Int32 nVersion = aIn.readInt16(); |
| (void)nVersion; |
| sal_Int32 nLocaleCount = aIn.readInt16(); |
| sal_Int32 iDefault = aIn.readInt16(); |
| (void)iDefault; |
| |
| sal_Int32* pPositions = new sal_Int32[nLocaleCount + 1]; |
| for( sal_Int32 i = 0; i < nLocaleCount + 1; i++ ) |
| pPositions[i] = aIn.readInt32(); |
| |
| // Import locales |
| LocaleItem* pUseAsDefaultItem = NULL; |
| for( sal_Int32 i = 0; i < nLocaleCount; i++ ) |
| { |
| sal_Int32 nPos = pPositions[i]; |
| aIn.seek( nPos ); |
| |
| Locale aLocale; |
| aLocale.Language = aIn.readString(); |
| aLocale.Country = aIn.readString(); |
| aLocale.Variant = aIn.readString(); |
| |
| sal_Int32 nAfterStringPos = aIn.getPosition(); |
| sal_Int32 nSize = pPositions[i+1] - nAfterStringPos; |
| Reference< io::XInputStream > xInput = aIn.getInputStreamForSection( nSize ); |
| if( xInput.is() ) |
| { |
| LocaleItem* pLocaleItem = new LocaleItem( aLocale ); |
| if( iDefault == i ) |
| pUseAsDefaultItem = pLocaleItem; |
| m_aLocaleItemVector.push_back( pLocaleItem ); |
| implReadPropertiesFile( pLocaleItem, xInput ); |
| } |
| } |
| |
| if( pUseAsDefaultItem != NULL ) |
| setDefaultLocale( pUseAsDefaultItem->m_locale ); |
| |
| delete[] pPositions; |
| } |
| |
| |
| // ============================================================================= |
| // Private helper methods |
| |
| bool checkNamingSceme( const ::rtl::OUString& aName, const ::rtl::OUString& aNameBase, |
| Locale& aLocale ) |
| { |
| bool bSuccess = false; |
| |
| sal_Int32 nNameLen = aName.getLength(); |
| sal_Int32 nNameBaseLen = aNameBase.getLength(); |
| |
| // Name has to start with NameBase followed |
| // by a '_' and at least one more character |
| if( aName.indexOf( aNameBase ) == 0 && nNameBaseLen < nNameLen-1 && |
| aName.getStr()[nNameBaseLen] == '_' ) |
| { |
| bSuccess = true; |
| |
| sal_Int32 iStart = nNameBaseLen + 1; |
| sal_Int32 iNext_ = aName.indexOf( '_', iStart ); |
| if( iNext_ != -1 && iNext_ < nNameLen-1 ) |
| { |
| aLocale.Language = aName.copy( iStart, iNext_ - iStart ); |
| |
| iStart = iNext_ + 1; |
| iNext_ = aName.indexOf( '_', iStart ); |
| if( iNext_ != -1 && iNext_ < nNameLen-1 ) |
| { |
| aLocale.Country = aName.copy( iStart, iNext_ - iStart ); |
| aLocale.Variant = aName.copy( iNext_ + 1 ); |
| } |
| else |
| aLocale.Country = aName.copy( iStart ); |
| } |
| else |
| aLocale.Language = aName.copy( iStart ); |
| } |
| return bSuccess; |
| } |
| |
| void StringResourcePersistenceImpl::implLoadAllLocales( void ) |
| { |
| for( LocaleItemVectorIt it = m_aLocaleItemVector.begin(); it != m_aLocaleItemVector.end(); it++ ) |
| { |
| LocaleItem* pLocaleItem = *it; |
| if( pLocaleItem != NULL ) |
| loadLocale( pLocaleItem ); |
| } |
| } |
| |
| // Scan locale properties files helper |
| void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< ::rtl::OUString >& aContentSeq ) |
| { |
| Locale aDefaultLocale; |
| bool bDefaultFound = false; |
| |
| sal_Int32 nCount = aContentSeq.getLength(); |
| const ::rtl::OUString* pFiles = aContentSeq.getConstArray(); |
| for( int i = 0 ; i < nCount ; i++ ) |
| { |
| ::rtl::OUString aCompleteName = pFiles[i]; |
| rtl::OUString aPureName; |
| rtl::OUString aExtension; |
| sal_Int32 iDot = aCompleteName.lastIndexOf( '.' ); |
| sal_Int32 iSlash = aCompleteName.lastIndexOf( '/' ); |
| if( iDot != -1 ) |
| { |
| sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0; |
| aPureName = aCompleteName.copy( iCopyFrom, iDot-iCopyFrom ); |
| aExtension = aCompleteName.copy( iDot + 1 ); |
| } |
| |
| if( aExtension.equalsAscii( "properties" ) ) |
| { |
| //rtl::OUString aName = aInetObj.getBase(); |
| Locale aLocale; |
| |
| if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) ) |
| { |
| LocaleItem* pLocaleItem = new LocaleItem( aLocale, false ); |
| m_aLocaleItemVector.push_back( pLocaleItem ); |
| |
| if( m_pCurrentLocaleItem == NULL ) |
| m_pCurrentLocaleItem = pLocaleItem; |
| |
| if( m_pDefaultLocaleItem == NULL ) |
| { |
| m_pDefaultLocaleItem = pLocaleItem; |
| m_bDefaultModified = true; |
| } |
| } |
| } |
| else if( !bDefaultFound && aExtension.equalsAscii( "default" ) ) |
| { |
| //rtl::OUString aName = aInetObj.getBase(); |
| Locale aLocale; |
| |
| if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) ) |
| bDefaultFound = true; |
| } |
| } |
| if( bDefaultFound ) |
| { |
| LocaleItem* pLocaleItem = getItemForLocale( aDefaultLocale, false ); |
| if( pLocaleItem ) |
| { |
| m_pDefaultLocaleItem = pLocaleItem; |
| m_bDefaultModified = false; |
| } |
| } |
| } |
| |
| // Scan locale properties files |
| void StringResourcePersistenceImpl::implScanLocales( void ) |
| { |
| // Dummy implementation, method not called for this |
| // base class, but pure virtual not possible- |
| } |
| |
| bool StringResourcePersistenceImpl::loadLocale( LocaleItem* pLocaleItem ) |
| { |
| bool bSuccess = false; |
| |
| OSL_ENSURE( pLocaleItem, "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL" ); |
| if( pLocaleItem ) |
| { |
| if( pLocaleItem->m_bLoaded ) |
| { |
| bSuccess = true; |
| } |
| else |
| { |
| bSuccess = implLoadLocale( pLocaleItem ); |
| pLocaleItem->m_bLoaded = true; // = bSuccess??? -> leads to more tries |
| } |
| } |
| return bSuccess; |
| } |
| |
| bool StringResourcePersistenceImpl::implLoadLocale( LocaleItem* ) |
| { |
| // Dummy implementation, method not called for this |
| // base class, but pure virtual not possible- |
| return false; |
| } |
| |
| ::rtl::OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem ) |
| { |
| static ::rtl::OUString aUnder = ::rtl::OUString::createFromAscii( "_" ); |
| |
| OSL_ENSURE( pLocaleItem, |
| "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL" ); |
| Locale aLocale = pLocaleItem->m_locale; |
| |
| ::rtl::OUString aRetStr = aUnder; |
| aRetStr += aLocale.Language; |
| |
| ::rtl::OUString aCountry = aLocale.Country; |
| if( aCountry.getLength() ) |
| { |
| aRetStr += aUnder; |
| aRetStr += aCountry; |
| } |
| |
| ::rtl::OUString aVariant = aLocale.Variant; |
| if( aVariant.getLength() ) |
| { |
| aRetStr += aUnder; |
| aRetStr += aVariant; |
| } |
| return aRetStr; |
| } |
| |
| ::rtl::OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem |
| ( LocaleItem* pLocaleItem, const ::rtl::OUString& aNameBase ) |
| { |
| ::rtl::OUString aFileName = aNameBase; |
| if( aFileName.getLength() == 0 ) |
| aFileName = aNameBaseDefaultStr; |
| |
| aFileName += implGetNameScemeForLocaleItem( pLocaleItem ); |
| return aFileName; |
| } |
| |
| ::rtl::OUString StringResourcePersistenceImpl::implGetPathForLocaleItem |
| ( LocaleItem* pLocaleItem, const ::rtl::OUString& aNameBase, |
| const ::rtl::OUString& aLocation, bool bDefaultFile ) |
| { |
| ::rtl::OUString aFileName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase ); |
| INetURLObject aInetObj( aLocation ); |
| aInetObj.insertName( aFileName, sal_True, INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::ENCODE_ALL ); |
| if( bDefaultFile ) |
| aInetObj.setExtension( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("default") ) ); |
| else |
| aInetObj.setExtension( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("properties") ) ); |
| ::rtl::OUString aCompleteFileName = aInetObj.GetMainURL( INetURLObject::NO_DECODE ); |
| return aCompleteFileName; |
| } |
| |
| // White space according to Java property files specification in |
| // http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream) |
| inline bool isWhiteSpace( sal_Unicode c ) |
| { |
| bool bWhite = ( c == 0x0020 || // space |
| c == 0x0009 || // tab |
| c == 0x000a || // line feed, not always handled by TextInputStream |
| c == 0x000d || // carriage return, not always handled by TextInputStream |
| c == 0x000C ); // form feed |
| return bWhite; |
| } |
| |
| inline void skipWhites( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri ) |
| { |
| while( ri < nLen ) |
| { |
| if( !isWhiteSpace( pBuf[ri] ) ) |
| break; |
| ri++; |
| } |
| } |
| |
| inline bool isHexDigit( sal_Unicode c, sal_uInt16& nDigitVal ) |
| { |
| bool bRet = true; |
| if( c >= '0' && c <= '9' ) |
| nDigitVal = c - '0'; |
| else if( c >= 'a' && c <= 'f' ) |
| nDigitVal = c - 'a' + 10; |
| else if( c >= 'A' && c <= 'F' ) |
| nDigitVal = c - 'A' + 10; |
| else |
| bRet = false; |
| return bRet; |
| } |
| |
| sal_Unicode getEscapeChar( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri ) |
| { |
| sal_Int32 i = ri; |
| |
| sal_Unicode cRet = 0; |
| sal_Unicode c = pBuf[i]; |
| switch( c ) |
| { |
| case 't': |
| cRet = 0x0009; |
| break; |
| case 'n': |
| cRet = 0x000a; |
| break; |
| case 'f': |
| cRet = 0x000c; |
| break; |
| case 'r': |
| cRet = 0x000d; |
| break; |
| case '\\': |
| cRet = '\\'; |
| break; |
| case 'u': |
| { |
| // Skip multiple u |
| i++; |
| while( i < nLen && pBuf[i] == 'u' ) |
| i++; |
| |
| // Process hex digits |
| sal_Int32 nDigitCount = 0; |
| sal_uInt16 nDigitVal; |
| while( i < nLen && isHexDigit( pBuf[i], nDigitVal ) ) |
| { |
| cRet = 16 * cRet + nDigitVal; |
| |
| nDigitCount++; |
| if( nDigitCount == 4 ) |
| { |
| // Write back position |
| ri = i; |
| break; |
| } |
| i++; |
| } |
| break; |
| } |
| default: |
| cRet = c; |
| } |
| |
| return cRet; |
| } |
| |
| void CheckContinueInNextLine( Reference< io::XTextInputStream > xTextInputStream, |
| ::rtl::OUString& aLine, bool& bEscapePending, const sal_Unicode*& pBuf, |
| sal_Int32& nLen, sal_Int32& i ) |
| { |
| if( i == nLen && bEscapePending ) |
| { |
| bEscapePending = false; |
| |
| if( !xTextInputStream->isEOF() ) |
| { |
| aLine = xTextInputStream->readLine(); |
| nLen = aLine.getLength(); |
| pBuf = aLine.getStr(); |
| i = 0; |
| |
| skipWhites( pBuf, nLen, i ); |
| } |
| } |
| } |
| |
| bool StringResourcePersistenceImpl::implReadPropertiesFile |
| ( LocaleItem* pLocaleItem, const Reference< io::XInputStream >& xInputStream ) |
| { |
| if( !xInputStream.is() || pLocaleItem == NULL ) |
| return false; |
| |
| bool bSuccess = false; |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| Reference< io::XTextInputStream > xTextInputStream( xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextInputStream" ), m_xContext ), UNO_QUERY ); |
| |
| if( xTextInputStream.is() ) |
| { |
| Reference< io::XActiveDataSink> xActiveDataSink( xTextInputStream, UNO_QUERY ); |
| if( xActiveDataSink.is() ) |
| { |
| bSuccess = true; |
| |
| xActiveDataSink->setInputStream( xInputStream ); |
| |
| ::rtl::OUString aEncodingStr = ::rtl::OUString::createFromAscii |
| ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) ); |
| xTextInputStream->setEncoding( aEncodingStr ); |
| |
| ::rtl::OUString aLine; |
| while( !xTextInputStream->isEOF() ) |
| { |
| aLine = xTextInputStream->readLine(); |
| |
| sal_Int32 nLen = aLine.getLength(); |
| if( 0 == nLen ) |
| continue; |
| const sal_Unicode* pBuf = aLine.getStr(); |
| ::rtl::OUStringBuffer aBuf; |
| sal_Unicode c = 0; |
| sal_Int32 i = 0; |
| |
| skipWhites( pBuf, nLen, i ); |
| if( i == nLen ) |
| continue; // line contains only white spaces |
| |
| // Comment? |
| c = pBuf[i]; |
| if( c == '#' || c == '!' ) |
| continue; |
| |
| // Scan key |
| ::rtl::OUString aResourceID; |
| bool bEscapePending = false; |
| bool bStrComplete = false; |
| while( i < nLen && !bStrComplete ) |
| { |
| c = pBuf[i]; |
| if( bEscapePending ) |
| { |
| aBuf.append( getEscapeChar( pBuf, nLen, i ) ); |
| bEscapePending = false; |
| } |
| else |
| { |
| if( c == '\\' ) |
| { |
| bEscapePending = true; |
| } |
| else |
| { |
| if( c == ':' || c == '=' || isWhiteSpace( c ) ) |
| bStrComplete = true; |
| else |
| aBuf.append( c ); |
| } |
| } |
| i++; |
| |
| CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i ); |
| if( i == nLen ) |
| bStrComplete = true; |
| |
| if( bStrComplete ) |
| aResourceID = aBuf.makeStringAndClear(); |
| } |
| |
| // Ignore lines with empty keys |
| if( 0 == aResourceID.getLength() ) |
| continue; |
| |
| // Scan value |
| skipWhites( pBuf, nLen, i ); |
| |
| ::rtl::OUString aValueStr; |
| bEscapePending = false; |
| bStrComplete = false; |
| while( i < nLen && !bStrComplete ) |
| { |
| c = pBuf[i]; |
| if( c == 0x000a || c == 0x000d ) // line feed/carriage return, not always handled by TextInputStream |
| { |
| i++; |
| } |
| else |
| { |
| if( bEscapePending ) |
| { |
| aBuf.append( getEscapeChar( pBuf, nLen, i ) ); |
| bEscapePending = false; |
| } |
| else if( c == '\\' ) |
| bEscapePending = true; |
| else |
| aBuf.append( c ); |
| i++; |
| |
| CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i ); |
| } |
| if( i == nLen ) |
| bStrComplete = true; |
| |
| if( bStrComplete ) |
| aValueStr = aBuf.makeStringAndClear(); |
| } |
| |
| // Push into table |
| pLocaleItem->m_aIdToStringMap[ aResourceID ] = aValueStr; |
| implScanIdForNumber( aResourceID ); |
| IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap; |
| rIndexMap[ aResourceID ] = pLocaleItem->m_nNextIndex++; |
| } |
| } |
| } |
| |
| return bSuccess; |
| } |
| |
| |
| inline sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal ) |
| { |
| sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10)); |
| return cRet; |
| } |
| |
| void implWriteCharToBuffer( ::rtl::OUStringBuffer& aBuf, sal_Unicode cu, bool bKey ) |
| { |
| if( cu == '\\' ) |
| { |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)'\\' ); |
| } |
| else if( cu == 0x000a ) |
| { |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)'n' ); |
| } |
| else if( cu == 0x000d ) |
| { |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)'r' ); |
| } |
| else if( bKey && cu == '=' ) |
| { |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)'=' ); |
| } |
| else if( bKey && cu == ':' ) |
| { |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)':' ); |
| } |
| // ISO/IEC 8859-1 range according to: |
| // http://en.wikipedia.org/wiki/ISO/IEC_8859-1 |
| else if( (cu >= 0x20 && cu <= 0x7e) ) |
| //TODO: Check why (cu >= 0xa0 && cu <= 0xFF) |
| //is encoded in sample properties files |
| //else if( (cu >= 0x20 && cu <= 0x7e) || |
| // (cu >= 0xa0 && cu <= 0xFF) ) |
| { |
| aBuf.append( cu ); |
| } |
| else |
| { |
| // Unicode encoding |
| aBuf.append( (sal_Unicode)'\\' ); |
| aBuf.append( (sal_Unicode)'u' ); |
| |
| sal_uInt16 nVal = cu; |
| for( sal_uInt16 i = 0 ; i < 4 ; i++ ) |
| { |
| sal_uInt16 nDigit = nVal / 0x1000; |
| nVal -= nDigit * 0x1000; |
| nVal *= 0x10; |
| aBuf.append( getHexCharForDigit( nDigit ) ); |
| } |
| } |
| } |
| |
| void implWriteStringWithEncoding( const ::rtl::OUString& aStr, |
| Reference< io::XTextOutputStream > xTextOutputStream, bool bKey ) |
| { |
| static sal_Unicode cLineFeed = 0xa; |
| |
| (void)aStr; |
| (void)xTextOutputStream; |
| |
| ::rtl::OUStringBuffer aBuf; |
| sal_Int32 nLen = aStr.getLength(); |
| const sal_Unicode* pSrc = aStr.getStr(); |
| for( sal_Int32 i = 0 ; i < nLen ; i++ ) |
| { |
| sal_Unicode cu = pSrc[i]; |
| implWriteCharToBuffer( aBuf, cu, bKey ); |
| // TODO?: split long lines |
| } |
| if( !bKey ) |
| aBuf.append( cLineFeed ); |
| |
| ::rtl::OUString aWriteStr = aBuf.makeStringAndClear(); |
| xTextOutputStream->writeString( aWriteStr ); |
| } |
| |
| bool StringResourcePersistenceImpl::implWritePropertiesFile( LocaleItem* pLocaleItem, |
| const Reference< io::XOutputStream >& xOutputStream, const ::rtl::OUString& aComment ) |
| { |
| static ::rtl::OUString aAssignmentStr = ::rtl::OUString::createFromAscii( "=" ); |
| static ::rtl::OUString aLineFeedStr = ::rtl::OUString::createFromAscii( "\n" ); |
| |
| if( !xOutputStream.is() || pLocaleItem == NULL ) |
| return false; |
| |
| bool bSuccess = false; |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| Reference< io::XTextOutputStream > xTextOutputStream( xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TextOutputStream" ), m_xContext ), UNO_QUERY ); |
| |
| if( xTextOutputStream.is() ) |
| { |
| Reference< io::XActiveDataSource> xActiveDataSource( xTextOutputStream, UNO_QUERY ); |
| if( xActiveDataSource.is() ) |
| { |
| xActiveDataSource->setOutputStream( xOutputStream ); |
| |
| ::rtl::OUString aEncodingStr = ::rtl::OUString::createFromAscii |
| ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) ); |
| xTextOutputStream->setEncoding( aEncodingStr ); |
| |
| xTextOutputStream->writeString( aComment ); |
| xTextOutputStream->writeString( aLineFeedStr ); |
| |
| const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap; |
| if( rHashMap.size() > 0 ) |
| { |
| // Sort ids according to read order |
| const IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap; |
| IdToIndexMap::const_iterator it_index; |
| |
| // Find max/min index |
| sal_Int32 nMinIndex = -1; |
| sal_Int32 nMaxIndex = -1; |
| for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); it_index++ ) |
| { |
| sal_Int32 nIndex = (*it_index).second; |
| if( nMinIndex > nIndex || nMinIndex == -1 ) |
| nMinIndex = nIndex; |
| if( nMaxIndex < nIndex ) |
| nMaxIndex = nIndex; |
| } |
| sal_Int32 nTabSize = nMaxIndex - nMinIndex + 1; |
| |
| // Create sorted array of pointers to the id strings |
| const ::rtl::OUString** pIdPtrs = new const ::rtl::OUString*[nTabSize]; |
| sal_Int32 i; |
| for( i = 0 ; i < nTabSize ; i++ ) |
| pIdPtrs[i] = NULL; |
| for( it_index = rIndexMap.begin(); it_index != rIndexMap.end(); it_index++ ) |
| { |
| sal_Int32 nIndex = (*it_index).second; |
| pIdPtrs[nIndex - nMinIndex] = &((*it_index).first); |
| } |
| |
| // Write lines in correct order |
| for( i = 0 ; i < nTabSize ; i++ ) |
| { |
| const ::rtl::OUString* pStr = pIdPtrs[i]; |
| if( pStr != NULL ) |
| { |
| ::rtl::OUString aResourceID = *pStr; |
| IdToStringMap::const_iterator it = rHashMap.find( aResourceID ); |
| if( !( it == rHashMap.end() ) ) |
| { |
| implWriteStringWithEncoding( aResourceID, xTextOutputStream, true ); |
| xTextOutputStream->writeString( aAssignmentStr ); |
| ::rtl::OUString aValStr = (*it).second; |
| implWriteStringWithEncoding( aValStr, xTextOutputStream, false ); |
| } |
| } |
| } |
| |
| delete pIdPtrs; |
| } |
| |
| bSuccess = true; |
| } |
| } |
| return bSuccess; |
| } |
| |
| |
| // ============================================================================= |
| // StringResourceWithStorageImpl |
| // ============================================================================= |
| |
| // component operations |
| static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceWithStorageImpl() |
| { |
| Sequence< ::rtl::OUString > names(1); |
| names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResourceWithStorage") ); |
| return names; |
| } |
| |
| static ::rtl::OUString getImplementationName_StringResourceWithStorageImpl() |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResourceWithStorage") ); |
| } |
| |
| static Reference< XInterface > SAL_CALL create_StringResourceWithStorageImpl( |
| Reference< XComponentContext > const & xContext ) |
| SAL_THROW( () ) |
| { |
| return static_cast< ::cppu::OWeakObject * >( new StringResourceWithStorageImpl( xContext ) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext ) |
| : StringResourceWithStorageImpl_BASE( rxContext ) |
| , m_bStorageChanged( false ) |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| StringResourceWithStorageImpl::~StringResourceWithStorageImpl() |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XServiceInfo |
| // ----------------------------------------------------------------------------- |
| |
| ::rtl::OUString StringResourceWithStorageImpl::getImplementationName( ) throw (RuntimeException) |
| { |
| return getImplementationName_StringResourceWithStorageImpl(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_Bool StringResourceWithStorageImpl::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) |
| { |
| Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); |
| const ::rtl::OUString* pNames = aNames.getConstArray(); |
| const ::rtl::OUString* pEnd = pNames + aNames.getLength(); |
| for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) |
| ; |
| |
| return pNames != pEnd; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getSupportedServiceNames( ) throw (RuntimeException) |
| { |
| return getSupportedServiceNames_StringResourceWithStorageImpl(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XInitialization |
| // ----------------------------------------------------------------------------- |
| |
| void StringResourceWithStorageImpl::initialize( const Sequence< Any >& aArguments ) |
| throw (Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| if ( aArguments.getLength() != 5 ) |
| { |
| throw RuntimeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringResourceWithStorageImpl::initialize: invalid number of arguments!" ) ), |
| Reference< XInterface >() ); |
| } |
| |
| bool bOk = (aArguments[0] >>= m_xStorage); |
| if( bOk && !m_xStorage.is() ) |
| bOk = false; |
| |
| if( !bOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceWithStorageImpl::initialize: invalid storage" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| |
| implInitializeCommonParameters( aArguments ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // Forwarding calls to base class |
| |
| // XModifyBroadcaster |
| void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::addModifyListener( aListener ); |
| } |
| void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::removeModifyListener( aListener ); |
| } |
| |
| // XStringResourceResolver |
| ::rtl::OUString StringResourceWithStorageImpl::resolveString( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveString( ResourceID ) ; |
| } |
| ::rtl::OUString StringResourceWithStorageImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); |
| } |
| sal_Bool StringResourceWithStorageImpl::hasEntryForId( const ::rtl::OUString& ResourceID ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForId( ResourceID ) ; |
| } |
| sal_Bool StringResourceWithStorageImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID, |
| const Locale& locale ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); |
| } |
| Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getResourceIDs( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDs(); |
| } |
| Sequence< ::rtl::OUString > StringResourceWithStorageImpl::getResourceIDsForLocale |
| ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDsForLocale( locale ); |
| } |
| Locale StringResourceWithStorageImpl::getCurrentLocale() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getCurrentLocale(); |
| } |
| Locale StringResourceWithStorageImpl::getDefaultLocale( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getDefaultLocale(); |
| } |
| Sequence< Locale > StringResourceWithStorageImpl::getLocales( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getLocales(); |
| } |
| |
| // XStringResourceManager |
| sal_Bool StringResourceWithStorageImpl::isReadOnly() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::isReadOnly(); |
| } |
| void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); |
| } |
| void StringResourceWithStorageImpl::setDefaultLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException,NoSupportException) |
| { |
| StringResourceImpl::setDefaultLocale( locale ); |
| } |
| void StringResourceWithStorageImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setString( ResourceID, Str ); |
| } |
| void StringResourceWithStorageImpl::setStringForLocale |
| ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); |
| } |
| void StringResourceWithStorageImpl::removeId( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeId( ResourceID ); |
| } |
| void StringResourceWithStorageImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeIdForLocale( ResourceID, locale ); |
| } |
| void StringResourceWithStorageImpl::newLocale( const Locale& locale ) |
| throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::newLocale( locale ); |
| } |
| void StringResourceWithStorageImpl::removeLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeLocale( locale ); |
| } |
| sal_Int32 StringResourceWithStorageImpl::getUniqueNumericId( ) |
| throw (RuntimeException, NoSupportException) |
| { |
| return StringResourceImpl::getUniqueNumericId(); |
| } |
| |
| // XStringResourcePersistence |
| void StringResourceWithStorageImpl::store() |
| throw (NoSupportException, Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceWithStorageImpl::store(): Read only" ); |
| |
| bool bUsedForStore = true; |
| bool bStoreAll = m_bStorageChanged; |
| m_bStorageChanged = false; |
| if( !m_bModified && !bStoreAll ) |
| return; |
| |
| implStoreAtStorage( m_aNameBase, m_aComment, m_xStorage, bUsedForStore, bStoreAll ); |
| m_bModified = false; |
| } |
| |
| sal_Bool StringResourceWithStorageImpl::isModified( ) |
| throw (RuntimeException) |
| { |
| return StringResourcePersistenceImpl::isModified(); |
| } |
| void StringResourceWithStorageImpl::setComment( const ::rtl::OUString& Comment ) |
| throw (::com::sun::star::uno::RuntimeException) |
| { |
| StringResourcePersistenceImpl::setComment( Comment ); |
| } |
| void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment ) |
| throw (Exception, RuntimeException) |
| { |
| StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment ); |
| } |
| void StringResourceWithStorageImpl::storeToURL( const ::rtl::OUString& URL, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment, |
| const Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) |
| throw (Exception, RuntimeException) |
| { |
| StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler ); |
| } |
| Sequence< ::sal_Int8 > StringResourceWithStorageImpl::exportBinary( ) |
| throw (RuntimeException) |
| { |
| return StringResourcePersistenceImpl::exportBinary(); |
| } |
| void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| StringResourcePersistenceImpl::importBinary( Data ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XStringResourceWithStorage |
| |
| void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage ) |
| throw (Exception, RuntimeException) |
| { |
| setStorage( Storage ); |
| store(); |
| } |
| |
| void StringResourceWithStorageImpl::setStorage( const Reference< XStorage >& Storage ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| if( !Storage.is() ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii |
| ( "StringResourceWithStorageImpl::setStorage: invalid storage" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| |
| implLoadAllLocales(); |
| |
| m_xStorage = Storage; |
| m_bStorageChanged = true; |
| } |
| |
| |
| // ============================================================================= |
| // Private helper methods |
| // ============================================================================= |
| |
| // Scan locale properties files |
| void StringResourceWithStorageImpl::implScanLocales( void ) |
| { |
| Reference< container::XNameAccess > xNameAccess( m_xStorage, UNO_QUERY ); |
| if( xNameAccess.is() ) |
| { |
| Sequence< ::rtl::OUString > aContentSeq = xNameAccess->getElementNames(); |
| implScanLocaleNames( aContentSeq ); |
| } |
| |
| implLoadAllLocales(); |
| } |
| |
| // Loading |
| bool StringResourceWithStorageImpl::implLoadLocale( LocaleItem* pLocaleItem ) |
| { |
| bool bSuccess = false; |
| try |
| { |
| ::rtl::OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase ); |
| aStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".properties") ); |
| |
| Reference< io::XStream > xElementStream = |
| m_xStorage->openStreamElement( aStreamName, ElementModes::READ ); |
| |
| if( xElementStream.is() ) |
| { |
| Reference< io::XInputStream > xInputStream = xElementStream->getInputStream(); |
| if( xInputStream.is() ) |
| { |
| bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream ); |
| xInputStream->closeInput(); |
| } |
| } |
| } |
| catch( uno::Exception& ) |
| {} |
| |
| return bSuccess; |
| } |
| |
| |
| // ============================================================================= |
| // StringResourceWithLocationImpl |
| // ============================================================================= |
| |
| // component operations |
| static Sequence< ::rtl::OUString > getSupportedServiceNames_StringResourceWithLocationImpl() |
| { |
| Sequence< ::rtl::OUString > names(1); |
| names[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.resource.StringResourceWithLocation") ); |
| return names; |
| } |
| |
| static ::rtl::OUString getImplementationName_StringResourceWithLocationImpl() |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.StringResourceWithLocation") ); |
| } |
| |
| static Reference< XInterface > SAL_CALL create_StringResourceWithLocationImpl( |
| Reference< XComponentContext > const & xContext ) |
| SAL_THROW( () ) |
| { |
| return static_cast< ::cppu::OWeakObject * >( new StringResourceWithLocationImpl( xContext ) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext ) |
| : StringResourceWithLocationImpl_BASE( rxContext ) |
| , m_bLocationChanged( false ) |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| StringResourceWithLocationImpl::~StringResourceWithLocationImpl() |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XServiceInfo |
| // ----------------------------------------------------------------------------- |
| |
| ::rtl::OUString StringResourceWithLocationImpl::getImplementationName( ) throw (RuntimeException) |
| { |
| return getImplementationName_StringResourceWithLocationImpl(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_Bool StringResourceWithLocationImpl::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) |
| { |
| Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); |
| const ::rtl::OUString* pNames = aNames.getConstArray(); |
| const ::rtl::OUString* pEnd = pNames + aNames.getLength(); |
| for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) |
| ; |
| |
| return pNames != pEnd; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getSupportedServiceNames( ) throw (RuntimeException) |
| { |
| return getSupportedServiceNames_StringResourceWithLocationImpl(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XInitialization |
| // ----------------------------------------------------------------------------- |
| |
| void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArguments ) |
| throw (Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| if ( aArguments.getLength() != 6 ) |
| { |
| throw RuntimeException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM |
| ( "XInitialization::initialize: invalid number of arguments!" ) ), |
| Reference< XInterface >() ); |
| } |
| |
| bool bOk = (aArguments[0] >>= m_aLocation); |
| sal_Int32 nLen = m_aLocation.getLength(); |
| if( bOk && nLen == 0 ) |
| { |
| bOk = false; |
| } |
| else |
| { |
| if( m_aLocation.getStr()[nLen - 1] != '/' ) |
| m_aLocation += ::rtl::OUString::createFromAscii( "/" ); |
| } |
| |
| if( !bOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "XInitialization::initialize: invalid URL" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| |
| |
| bOk = (aArguments[5] >>= m_xInteractionHandler); |
| if( !bOk ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "StringResourceWithStorageImpl::initialize: invalid type" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 5 ); |
| } |
| |
| implInitializeCommonParameters( aArguments ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // Forwarding calls to base class |
| |
| // XModifyBroadcaster |
| void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::addModifyListener( aListener ); |
| } |
| void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) |
| throw (RuntimeException) |
| { |
| StringResourceImpl::removeModifyListener( aListener ); |
| } |
| |
| // XStringResourceResolver |
| ::rtl::OUString StringResourceWithLocationImpl::resolveString( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveString( ResourceID ) ; |
| } |
| ::rtl::OUString StringResourceWithLocationImpl::resolveStringForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw ( ::com::sun::star::resource::MissingResourceException, RuntimeException) |
| { |
| return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); |
| } |
| sal_Bool StringResourceWithLocationImpl::hasEntryForId( const ::rtl::OUString& ResourceID ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForId( ResourceID ) ; |
| } |
| sal_Bool StringResourceWithLocationImpl::hasEntryForIdAndLocale( const ::rtl::OUString& ResourceID, |
| const Locale& locale ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); |
| } |
| Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getResourceIDs( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDs(); |
| } |
| Sequence< ::rtl::OUString > StringResourceWithLocationImpl::getResourceIDsForLocale |
| ( const Locale& locale ) throw (::com::sun::star::uno::RuntimeException) |
| { |
| return StringResourceImpl::getResourceIDsForLocale( locale ); |
| } |
| Locale StringResourceWithLocationImpl::getCurrentLocale() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getCurrentLocale(); |
| } |
| Locale StringResourceWithLocationImpl::getDefaultLocale( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getDefaultLocale(); |
| } |
| Sequence< Locale > StringResourceWithLocationImpl::getLocales( ) |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::getLocales(); |
| } |
| |
| // XStringResourceManager |
| sal_Bool StringResourceWithLocationImpl::isReadOnly() |
| throw (RuntimeException) |
| { |
| return StringResourceImpl::isReadOnly(); |
| } |
| void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); |
| } |
| void StringResourceWithLocationImpl::setDefaultLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException,NoSupportException) |
| { |
| StringResourceImpl::setDefaultLocale( locale ); |
| } |
| void StringResourceWithLocationImpl::setString( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setString( ResourceID, Str ); |
| } |
| void StringResourceWithLocationImpl::setStringForLocale |
| ( const ::rtl::OUString& ResourceID, const ::rtl::OUString& Str, const Locale& locale ) |
| throw (NoSupportException, RuntimeException) |
| { |
| StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); |
| } |
| void StringResourceWithLocationImpl::removeId( const ::rtl::OUString& ResourceID ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeId( ResourceID ); |
| } |
| void StringResourceWithLocationImpl::removeIdForLocale( const ::rtl::OUString& ResourceID, const Locale& locale ) |
| throw (::com::sun::star::resource::MissingResourceException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeIdForLocale( ResourceID, locale ); |
| } |
| void StringResourceWithLocationImpl::newLocale( const Locale& locale ) |
| throw (ElementExistException, IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::newLocale( locale ); |
| } |
| void StringResourceWithLocationImpl::removeLocale( const Locale& locale ) |
| throw (IllegalArgumentException, RuntimeException, NoSupportException) |
| { |
| StringResourceImpl::removeLocale( locale ); |
| } |
| sal_Int32 StringResourceWithLocationImpl::getUniqueNumericId( ) |
| throw (RuntimeException, NoSupportException) |
| { |
| return StringResourceImpl::getUniqueNumericId(); |
| } |
| |
| // XStringResourcePersistence |
| void StringResourceWithLocationImpl::store() |
| throw (NoSupportException, Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceWithLocationImpl::store(): Read only" ); |
| |
| bool bUsedForStore = true; |
| bool bStoreAll = m_bLocationChanged; |
| m_bLocationChanged = false; |
| if( !m_bModified && !bStoreAll ) |
| return; |
| |
| Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess(); |
| implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment, |
| xFileAccess, bUsedForStore, bStoreAll ); |
| m_bModified = false; |
| } |
| |
| sal_Bool StringResourceWithLocationImpl::isModified( ) |
| throw (RuntimeException) |
| { |
| return StringResourcePersistenceImpl::isModified(); |
| } |
| void StringResourceWithLocationImpl::setComment( const ::rtl::OUString& Comment ) |
| throw (::com::sun::star::uno::RuntimeException) |
| { |
| StringResourcePersistenceImpl::setComment( Comment ); |
| } |
| void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment ) |
| throw (Exception, RuntimeException) |
| { |
| StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment ); |
| } |
| void StringResourceWithLocationImpl::storeToURL( const ::rtl::OUString& URL, |
| const ::rtl::OUString& NameBase, const ::rtl::OUString& Comment, |
| const Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) |
| throw (Exception, RuntimeException) |
| { |
| StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler ); |
| } |
| Sequence< ::sal_Int8 > StringResourceWithLocationImpl::exportBinary( ) |
| throw (RuntimeException) |
| { |
| return StringResourcePersistenceImpl::exportBinary(); |
| } |
| void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| StringResourcePersistenceImpl::importBinary( Data ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // XStringResourceWithLocation |
| |
| // XStringResourceWithLocation |
| void StringResourceWithLocationImpl::storeAsURL( const ::rtl::OUString& URL ) |
| throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) |
| { |
| setURL( URL ); |
| store(); |
| } |
| |
| void StringResourceWithLocationImpl::setURL( const ::rtl::OUString& URL ) |
| throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| implCheckReadOnly( "StringResourceWithLocationImpl::setURL(): Read only" ); |
| |
| sal_Int32 nLen = URL.getLength(); |
| if( nLen == 0 ) |
| { |
| ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii |
| ( "StringResourceWithLocationImpl::setURL: invalid URL" ); |
| throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 ); |
| } |
| |
| implLoadAllLocales(); |
| |
| // Delete files at old location |
| bool bUsedForStore = false; |
| bool bStoreAll = false; |
| bool bKillAll = true; |
| implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment, |
| getFileAccess(), bUsedForStore, bStoreAll, bKillAll ); |
| |
| m_aLocation = URL; |
| m_bLocationChanged = true; |
| } |
| |
| |
| // ============================================================================= |
| // Private helper methods |
| // ============================================================================= |
| |
| // Scan locale properties files |
| void StringResourceWithLocationImpl::implScanLocales( void ) |
| { |
| const Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess(); |
| if( xFileAccess.is() && xFileAccess->isFolder( m_aLocation ) ) |
| { |
| Sequence< ::rtl::OUString > aContentSeq = xFileAccess->getFolderContents( m_aLocation, false ); |
| implScanLocaleNames( aContentSeq ); |
| } |
| } |
| |
| // Loading |
| bool StringResourceWithLocationImpl::implLoadLocale( LocaleItem* pLocaleItem ) |
| { |
| bool bSuccess = false; |
| |
| const Reference< ucb::XSimpleFileAccess > xFileAccess = getFileAccess(); |
| if( xFileAccess.is() ) |
| { |
| ::rtl::OUString aCompleteFileName = |
| implGetPathForLocaleItem( pLocaleItem, m_aNameBase, m_aLocation ); |
| |
| Reference< io::XInputStream > xInputStream; |
| try |
| { |
| xInputStream = xFileAccess->openFileRead( aCompleteFileName ); |
| } |
| catch( Exception& ) |
| {} |
| if( xInputStream.is() ) |
| { |
| bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream ); |
| xInputStream->closeInput(); |
| } |
| } |
| |
| return bSuccess; |
| } |
| |
| const Reference< ucb::XSimpleFileAccess > StringResourceWithLocationImpl::getFileAccess( void ) |
| { |
| ::osl::MutexGuard aGuard( getMutex() ); |
| |
| if( !m_xSFI.is() ) |
| { |
| Reference< XMultiComponentFactory > xMCF = getMultiComponentFactory(); |
| m_xSFI = Reference< ucb::XSimpleFileAccess >( xMCF->createInstanceWithContext |
| ( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), m_xContext ), UNO_QUERY ); |
| |
| if( m_xSFI.is() && m_xInteractionHandler.is() ) |
| m_xSFI->setInteractionHandler( m_xInteractionHandler ); |
| } |
| return m_xSFI; |
| } |
| |
| |
| // ============================================================================= |
| // component export operations |
| // ============================================================================= |
| |
| static struct ::cppu::ImplementationEntry s_component_entries [] = |
| { |
| { |
| create_StringResourceImpl, getImplementationName_StringResourceImpl, |
| getSupportedServiceNames_StringResourceImpl, |
| ::cppu::createSingleComponentFactory, |
| 0, 0 |
| }, |
| { |
| create_StringResourceWithLocationImpl, getImplementationName_StringResourceWithLocationImpl, |
| getSupportedServiceNames_StringResourceWithLocationImpl, |
| ::cppu::createSingleComponentFactory, |
| 0, 0 |
| }, |
| { |
| create_StringResourceWithStorageImpl, getImplementationName_StringResourceWithStorageImpl, |
| getSupportedServiceNames_StringResourceWithStorageImpl, |
| ::cppu::createSingleComponentFactory, |
| 0, 0 |
| }, |
| { 0, 0, 0, 0, 0, 0 } |
| }; |
| |
| |
| //......................................................................... |
| } // namespace dlgprov |
| //......................................................................... |
| |
| |
| // ============================================================================= |
| // component exports |
| // ============================================================================= |
| |
| extern "C" |
| { |
| void SAL_CALL component_getImplementationEnvironment( |
| const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) |
| { |
| (void)ppEnv; |
| |
| *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; |
| } |
| |
| void * SAL_CALL component_getFactory( |
| const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager, |
| registry::XRegistryKey * pRegistryKey ) |
| { |
| return ::cppu::component_getFactoryHelper( |
| pImplName, pServiceManager, pRegistryKey, ::stringresource::s_component_entries ); |
| } |
| } |