blob: 78c3fe5fb60e6929c0833a66c172844dd2d94d16 [file] [log] [blame]
/**************************************************************
*
* 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 );
}
}