2
0
Fork 0

Refactored internal api

This commit is contained in:
Willem Cazander 2012-06-04 22:49:12 +02:00
parent 3f31bb8a3a
commit 6ccd763d1f
361 changed files with 23049 additions and 4498 deletions

View file

@ -63,8 +63,8 @@ abstract public class AbstractRootApplicationBundle extends MergeableResourceBun
config.parseConfig();
applicationSupportedLocales = config.getApplicationSupportedLocales();
bundleConfigs = config.getBundleConfigs();
for (BundleConfig bc:bundleConfigs) {
addBundleData(config.loadBundleConfig(bc,getLocale()));
for (BundleConfig bundleConfig:bundleConfigs) {
addBundleData(config.loadBundleConfigData(bundleConfig,getLocale()));
}
}

View file

@ -27,7 +27,6 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.logging.Logger;
/**
* MergeableResourceBundle is an ResourceBundle which can merge different bundles into one.
@ -37,14 +36,12 @@ import java.util.logging.Logger;
*/
public class MergeableResourceBundle extends ResourceBundle {
private Logger logger = null;
private Map<String,String> bundleData = null;
/**
* Creates an new MergeableResourceBundle instance.
*/
public MergeableResourceBundle() {
logger = Logger.getLogger(MergeableResourceBundle.class.getName());
bundleData = new HashMap<String,String>(500);
init();
}
@ -59,7 +56,6 @@ public class MergeableResourceBundle extends ResourceBundle {
* Protected method to clear the bundle data.
*/
protected void clear() {
logger.fine("Clearing bundle data current size: "+bundleData.size());
bundleData.clear();
}
@ -84,9 +80,7 @@ public class MergeableResourceBundle extends ResourceBundle {
* @param dataMap
*/
public void addBundleData(Map<String,String> dataMap) {
int startSize = bundleData.size();
bundleData.putAll(dataMap);
logger.fine("Adding bundle data: "+dataMap.size()+" orgSize: "+startSize+" newSize: "+bundleData.size());
}
/**
@ -94,11 +88,9 @@ public class MergeableResourceBundle extends ResourceBundle {
* @param bundle
*/
public void addBundleData(ResourceBundle bundle) {
int startSize = bundleData.size();
for (String key:bundle.keySet()) {
String value = bundle.getString(key);
bundleData.put(key, value);
}
logger.fine("Adding bundle data: "+bundle.keySet().size()+" orgSize: "+startSize+" newSize: "+bundleData.size());
}
}

View file

@ -33,6 +33,8 @@ import net.forwardfire.vasc.lib.i18n.SupportedBundleLocale;
*/
public class RootApplicationBundle extends AbstractRootApplicationBundle {
static public final String URI = RootApplicationBundle.class.getName();
@Override
public SupportedBundleLocale getSupportedBundleLocale() {
return SupportedBundleLocale.DEFAULT_LOCALE;

View file

@ -0,0 +1,64 @@
package net.forwardfire.vasc.lib.i18n.config;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;
/**
* BundleCharSetControl load ResourceBundles with correct CharSet.
*
* @author Willem Cazander
* @version 1.0 May 8, 2012
*/
public class BundleCharSetControl extends Control {
/** The default extension for bundles. */
protected static final String BUNDLE_EXTENSION = "properties";
/** The charSet to load with **/
protected Charset charSet = null;
/**
* Creates BundleCharSetControl to read ResourceBundle with charSet.
*/
public BundleCharSetControl(Charset charSet) {
this.charSet=charSet;
}
/**
* Does the loading of the ResourceBundle
*/
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, charSet));
} finally {
stream.close();
}
}
return bundle;
}
}

View file

@ -22,6 +22,8 @@
package net.forwardfire.vasc.lib.i18n.config;
import java.nio.charset.Charset;
/**
* BundleConfig holds the config to load one bundle.
*
@ -35,7 +37,7 @@ public class BundleConfig {
private String exclude = null;
private BundleURIType uriType = BundleURIType.RESOURCE;
private BundleFormat format = BundleFormat.BUNDLE;
private boolean utf8 = true;
private Charset charSet = null;
private boolean optional = false;
/**
@ -109,19 +111,19 @@ public class BundleConfig {
}
/**
* @return the utf8
* @return the charSet
*/
public boolean isUtf8() {
return utf8;
public Charset getCharSet() {
return charSet;
}
/**
* @param utf8 the utf8 to set
* @param charSet the charSet to set
*/
public void setUtf8(boolean utf8) {
this.utf8 = utf8;
public void setCharSet(Charset charSet) {
this.charSet = charSet;
}
/**
* @return the optional
*/

View file

@ -25,19 +25,18 @@ package net.forwardfire.vasc.lib.i18n.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;
import java.util.logging.Logger;
/**
@ -50,34 +49,51 @@ public class BundleConfigParser {
private Logger logger = null;
public static final String CONFIG_RESOURCE_DEFAULT = "META-INF/root-bundle.properties";
protected static final String BUNDLE_EXTENSION = "properties";
protected static final Control UTF8_CONTROL = new UTF8Control();
protected static final String DEFAULT_CHAR_SET = "UTF-8";
protected List<Locale> applicationSupportedLocales = null;
protected List<BundleConfig> bundlesConfigs = null;
protected List<BundleConfig> bundlesConfigs = null;
protected List<String> bundleNames = null;
protected Charset defaultCharSet = null;
/**
* Creates new BundleConfigParser object.
*/
public BundleConfigParser() {
logger = Logger.getLogger(BundleConfigParser.class.getName());
applicationSupportedLocales = new ArrayList<Locale>(10);
bundlesConfigs = new ArrayList<BundleConfig>(10);
defaultCharSet = Charset.forName(DEFAULT_CHAR_SET);
bundleNames = new ArrayList<String>(10);
}
/**
* Cleans config and
*/
public void parseConfig() {
bundlesConfigs.clear();
applicationSupportedLocales.clear();
cleanConfig();
Properties properties = new Properties();
readPropertiesResource(properties,CONFIG_RESOURCE_DEFAULT);
readPropertiesConfig(properties);
parseProperties(properties);
}
/**
* Returns List of supported locales by this root bundle config.
*/
public List<Locale> getApplicationSupportedLocales() {
return applicationSupportedLocales;
}
/**
* Returns List of ordered bundle configs to load into root bundle.
*/
public List<BundleConfig> getBundleConfigs() {
return bundlesConfigs;
}
public Map<String,String> loadBundleConfig(BundleConfig bundle,Locale locale) {
/**
* Loads BundleConfig and returns localized data as map.
*/
public Map<String,String> loadBundleConfigData(BundleConfig bundle,Locale locale) {
Properties properties = new Properties();
try {
switch (bundle.getUriType()) {
@ -86,10 +102,10 @@ public class BundleConfigParser {
readPropertiesBundle(properties,bundle,locale);
break;
case URL:
readPropertiesStream(properties,new URL(bundle.getUri()).openStream());
readPropertiesBundleUrl(properties,bundle,new URL(bundle.getUri()));
break;
case FILE:
readPropertiesFile(properties,new File(bundle.getUri()));
readPropertiesBundleFile(properties,bundle,new File(bundle.getUri()));
break;
}
} catch (Exception e) {
@ -113,55 +129,17 @@ public class BundleConfigParser {
return result;
}
protected void readPropertiesFile(Properties p,File file) {
logger.info("Reading bundle file: "+file.getAbsoluteFile());
try {
readPropertiesStream(p,new FileInputStream(file));
} catch (Exception e) {
throw new RuntimeException("Could not load resource file error: "+e.getMessage(),e);
}
}
protected void readPropertiesBundle(Properties p,BundleConfig bundle,Locale locale) {
ResourceBundle bundleReal = null;
if (bundle.isUtf8()) {
bundleReal = ResourceBundle.getBundle(bundle.getUri(),locale,UTF8_CONTROL);
} else {
bundleReal = ResourceBundle.getBundle(bundle.getUri(),locale);
}
for (String key:bundleReal.keySet()) {
String value = bundleReal.getString(key);
p.put(key, value);
}
}
protected void readPropertiesResource(Properties p,String resource) {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = p.getClass().getClassLoader(); // fallback
}
readPropertiesStream(p,cl.getResourceAsStream(resource));
} catch (Exception e) {
throw new RuntimeException("Could not load resource: "+resource+" error: "+e.getMessage(),e);
}
}
protected void readPropertiesStream(Properties p,InputStream in) {
try {
p.load(in);
} catch (Exception e) {
throw new RuntimeException("Could not load properties error: "+e.getMessage(),e);
} finally {
if (in!=null) {
try {
in.close();
} catch (IOException e) {
}
}
}
/**
* Cleans bundle configs and supported locales.
*/
protected void cleanConfig() {
bundlesConfigs.clear();
applicationSupportedLocales.clear();
}
/**
* Parsed the root-bundle.properties file format.
*/
protected void parseProperties(Properties p) {
Map<String,BundleConfig> bundles = new HashMap<String,BundleConfig>(10);
for (Object keyO:p.keySet()) {
@ -177,6 +155,15 @@ public class BundleConfigParser {
applicationSupportedLocales.add(new Locale(keyField));
continue;
}
if ("config".equals(keyConfig)) {
if ("charset".equals(keyField)) {
defaultCharSet = Charset.forName(value);
} else if ("bundles".equals(keyField)) {
String[] configBundles = value.split(",");
bundleNames.addAll(Arrays.asList(configBundles));
}
continue;
}
BundleConfig c = bundles.get(keyConfig);
if (c==null) {
@ -194,44 +181,90 @@ public class BundleConfigParser {
c.setFormat(BundleFormat.valueOf(value));
} else if ("optional".equals(keyField)) {
c.setOptional(new Boolean(value));
} else if ("utf8".equals(keyField)) {
c.setUtf8(new Boolean(value));
} else if ("charset".equals(keyField)) {
c.setCharSet(Charset.forName(value));
}
}
if (bundleNames.isEmpty()) {
bundlesConfigs.addAll(bundles.values());
} else {
for (String bundleName:bundleNames) {
BundleConfig bundle = bundles.get(bundleName);
bundlesConfigs.add(bundle);
}
}
for (BundleConfig bundle:bundlesConfigs) {
if (bundle.getCharSet()==null) {
bundle.setCharSet(defaultCharSet);
}
}
bundlesConfigs.addAll(bundles.values());
}
protected static class UTF8Control extends Control {
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
// The below code is copied from default Control#newBundle() implementation.
// Only the PropertyResourceBundle line is changed to read the file as UTF-8.
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
} finally {
stream.close();
}
}
return bundle;
}
}
/**
* Reads properties file from disk.
*/
protected void readPropertiesBundleFile(Properties p,BundleConfig bundle,File file) {
logger.fine("Reading bundle file: "+file.getAbsoluteFile());
try {
readProperties(p,new InputStreamReader(new FileInputStream(file),bundle.getCharSet()));
} catch (Exception e) {
throw new RuntimeException("Could not load resource file error: "+e.getMessage(),e);
}
}
/**
* Reads properties file from url.
*/
protected void readPropertiesBundleUrl(Properties p,BundleConfig bundle,URL url) {
logger.fine("Reading bundle url: "+url.toString());
try {
readProperties(p,new InputStreamReader(url.openStream(),bundle.getCharSet()));
} catch (Exception e) {
throw new RuntimeException("Could not load resource file error: "+e.getMessage(),e);
}
}
/**
* Read ResourceBundle from classpath.
*/
protected void readPropertiesBundle(Properties p,BundleConfig bundle,Locale locale) {
ResourceBundle bundleReal = ResourceBundle.getBundle(bundle.getUri(),locale,new BundleCharSetControl(bundle.getCharSet()));
for (String key:bundleReal.keySet()) {
String value = bundleReal.getString(key);
p.put(key, value);
}
}
/**
* Read properties from Reader and close Reader.
*/
protected void readProperties(Properties p,Reader in) {
try {
p.load(in);
} catch (Exception e) {
throw new RuntimeException("Could not load properties error: "+e.getMessage(),e);
} finally {
if (in!=null) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
/**
* Read properties file from resource classpath.
*/
protected void readPropertiesConfig(Properties p) {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = p.getClass().getClassLoader(); // fallback
}
readProperties(p,new InputStreamReader(cl.getResourceAsStream(CONFIG_RESOURCE_DEFAULT),defaultCharSet));
} catch (Exception e) {
throw new RuntimeException("Could not load resource: "+CONFIG_RESOURCE_DEFAULT+" error: "+e.getMessage(),e);
}
}
}

View file

@ -1,8 +1,11 @@
package net.forwardfire.vasc.lib.i18n;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import net.forwardfire.vasc.lib.i18n.bundle.RootApplicationBundle;
import net.forwardfire.vasc.lib.i18n.config.BundleConfig;
import net.forwardfire.vasc.lib.i18n.config.BundleConfigParser;
import junit.framework.TestCase;
@ -15,16 +18,34 @@ import junit.framework.TestCase;
*/
public class RootBundleTest extends TestCase {
static private final String TEST_BUNDLE = RootApplicationBundle.URI;
static private final Locale TEST_LOCALE = new Locale("en");
static private final Locale TEST_LOCALE_NL = new Locale("nl");
public void testParser() {
BundleConfigParser p = new BundleConfigParser();
p.parseConfig();
assertEquals(2,p.getBundleConfigs().size());
assertEquals(2,p.getApplicationSupportedLocales().size());
}
public void testBundleOrder() {
BundleConfigParser p = new BundleConfigParser();
p.parseConfig();
List<BundleConfig> conf = p.getBundleConfigs();
assertTrue(conf.isEmpty()==false);
BundleConfig bundle = conf.get(0);
assertEquals("bundle2",bundle.getName());
}
public void testBundleOrderValue() {
ResourceBundle bundle = ResourceBundle.getBundle(TEST_BUNDLE,TEST_LOCALE);
assertEquals("bundle1",bundle.getString("bundle.key"));
}
public void testValues_en() {
ResourceBundle bundle = ResourceBundle.getBundle("net.forwardfire.vasc.lib.i18n.bundle.RootApplicationBundle",new Locale("en"));
assertEquals(6,bundle.keySet().size());
ResourceBundle bundle = ResourceBundle.getBundle(TEST_BUNDLE,TEST_LOCALE);
assertEquals(7,bundle.keySet().size());
assertEquals("key1_en",bundle.getString("bundle1.key1"));
assertEquals("key2_en",bundle.getString("bundle1.key2"));
assertEquals("key3_en",bundle.getString("bundle1.key3"));
@ -34,8 +55,8 @@ public class RootBundleTest extends TestCase {
}
public void testValues_nl() {
ResourceBundle bundle = ResourceBundle.getBundle("net.forwardfire.vasc.lib.i18n.bundle.RootApplicationBundle",new Locale("nl"));
assertEquals(6,bundle.keySet().size());
ResourceBundle bundle = ResourceBundle.getBundle(TEST_BUNDLE,TEST_LOCALE_NL);
assertEquals(7,bundle.keySet().size());
assertEquals("key1_nl",bundle.getString("bundle1.key1"));
assertEquals("key2_nl",bundle.getString("bundle1.key2"));
assertEquals("key3_nl",bundle.getString("bundle1.key3"));

View file

@ -1,4 +1,8 @@
# Default config
config.charset=UTF-8
config.bundles=bundle2,bundle1
# We only suport 2 languages.
locale.nl=true
locale.en=true
@ -7,12 +11,13 @@ locale.en=true
bundle1.uri=net.forwardfire.vasc.lib.i18n.resources.TestBundle1
bundle2.uri=net.forwardfire.vasc.lib.i18n.resources.TestBundle2
# TODO:
#
# Bundle options;
#
# bundle2.type=RESOURCE
# bundle2.exclude=yoyo.*
# bundle2.format=PROPERTIES
# bundle2.utf8=true
# bundle2.charset=UTF-8
# bundle2.optional=false
#
# bundle3.uri=http://foo.bar/some/path/bundle.properties

View file

@ -1,4 +1,6 @@
# Test bundle
bundle.key = bundle1
bundle1.key1 = key1_en
bundle1.key2 = key2_en
bundle1.key3 = key3_en

View file

@ -1,4 +1,5 @@
# Test bundle
bundle.key = bundle1
bundle1.key1 = key1_nl
bundle1.key2 = key2_nl
bundle1.key3 = key3_nl

View file

@ -1,4 +1,5 @@
# Test bundle
bundle.key = bundle2
bundle2.key1 = key1_en
bundle2.key2 = key2_en
bundle2.key3 = key3_en

View file

@ -1,4 +1,5 @@
# Test bundle
bundle.key = bundle2
bundle2.key1 = key1_nl
bundle2.key2 = key2_nl
bundle2.key3 = key3_nl