/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.localization;
import java.io.IOException;
import java.util.Locale;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.enonic.cms.framework.cache.CacheFacade;
import com.enonic.cms.framework.cache.CacheManager;
import com.enonic.cms.core.resource.ResourceFile;
import com.enonic.cms.core.resource.ResourceKey;
import com.enonic.cms.core.resource.ResourceService;
import com.enonic.cms.core.structure.SiteEntity;
@Component
public final class LocalizationResourceBundleServiceImpl
implements LocalizationResourceBundleService, InitializingBean
{
private ResourceService resourceService;
private CacheFacade cacheFacade;
private long checkInterval = 5000;
private LocalizationPropertiesCache propertiesCache;
@Override
public LocalizationResourceBundle getResourceBundle( final SiteEntity site, final Locale locale )
{
final ResourceKey defaultLocalizationResourceKey = site.getDefaultLocalizationResource();
if ( defaultLocalizationResourceKey == null )
{
return null;
}
return createResourceBundle( locale, defaultLocalizationResourceKey );
}
private Properties loadBundle( final ResourceKey defaultLocalizationResourceKey, final String bundleExtension )
{
final String defaultLocalizationResourceName = defaultLocalizationResourceKey.toString();
final int pos = defaultLocalizationResourceName.lastIndexOf( '.' );
String bundleResourceKey = defaultLocalizationResourceName;
if ( pos > 0 )
{
bundleResourceKey = defaultLocalizationResourceName.substring( 0, pos );
}
bundleResourceKey = bundleResourceKey + bundleExtension + ".properties";
return getOrCreateProperties( ResourceKey.from( bundleResourceKey ) );
}
private Properties getOrCreateProperties( final ResourceKey resourceKey )
{
Properties properties = getFromCache( resourceKey );
if ( properties == null )
{
properties = loadPropertiesFromFile( resourceKey );
}
return properties;
}
private synchronized Properties loadPropertiesFromFile( final ResourceKey resourceKey )
{
Properties properties = getFromCache( resourceKey );
if ( properties != null )
{
return properties;
}
properties = new Properties();
final ResourceFile resourceFile = resourceService.getResourceFile( resourceKey );
if ( resourceFile != null )
{
try
{
properties.load( resourceFile.getDataAsInputStream() );
}
catch ( final IOException e )
{
throw new LocalizationResourceException( "Not able to load resource: " + resourceFile.getName(), e );
}
}
putInCache( resourceKey, properties );
return properties;
}
private void putInCache( final ResourceKey resourceKey, final Properties properties )
{
this.propertiesCache.put( new LocalizationPropertiesCacheEntry( resourceKey, properties ) );
}
private Properties getFromCache( final ResourceKey resourceKey )
{
final LocalizationPropertiesCacheEntry entry = this.propertiesCache.get( resourceKey );
return entry != null ? entry.getProperties() : null;
}
private LocalizationResourceBundle createResourceBundle( final Locale locale, final ResourceKey defaultLocalizationResourceKey )
{
Properties props = new Properties();
String lang = locale.getLanguage();
String country = locale.getCountry();
String variant = locale.getVariant();
props.putAll( loadBundle( defaultLocalizationResourceKey, "" ) );
if ( StringUtils.isNotEmpty( lang ) )
{
lang = lang.toLowerCase();
props.putAll( loadBundle( defaultLocalizationResourceKey, "_" + lang ) );
}
if ( StringUtils.isNotEmpty( country ) )
{
country = country.toLowerCase();
props.putAll( loadBundle( defaultLocalizationResourceKey, "_" + lang + "_" + country ) );
}
if ( StringUtils.isNotEmpty( variant ) )
{
variant = variant.toLowerCase();
props.putAll( loadBundle( defaultLocalizationResourceKey, "_" + lang + "_" + country + "_" + variant ) );
}
return new LocalizationResourceBundle( props );
}
@Autowired
public void setResourceService( final ResourceService resourceService )
{
this.resourceService = resourceService;
}
@Autowired
public void setCacheManager( final CacheManager cacheManager )
{
this.cacheFacade = cacheManager.getLocalizationCache();
}
@Value("${cms.cache.localization.checkInterval}")
public void setCheckInterval( final long checkInterval )
{
this.checkInterval = checkInterval;
}
@Override
public void afterPropertiesSet()
{
this.propertiesCache = new LocalizationPropertiesCache( this.cacheFacade, this.resourceService, this.checkInterval );
}
}