You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by do...@apache.org on 2001/02/26 01:39:43 UTC
cvs commit: jakarta-avalon/proposal/4.0/src/java/org/apache/aut/i18n ResourceGroup.java XMLResourceBundle.java XMLResourceBundleFactory.java XPathAPI.java
donaldp 01/02/25 16:39:43
Added: proposal/4.0/src/java/org/apache/aut/i18n ResourceGroup.java
XMLResourceBundle.java
XMLResourceBundleFactory.java XPathAPI.java
Log:
Added i18n util to aut
Revision Changes Path
1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/aut/i18n/ResourceGroup.java
Index: ResourceGroup.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.aut.i18n;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Random;
import java.util.ResourceBundle;
/**
* A class used to manage resource bundles.
*/
public class ResourceGroup
{
protected final static Random RANDOM = new Random();
protected final HashMap m_bundles = new HashMap();
protected final Locale m_locale;
/**
* Create a ResourceGroup to manage resource bundles for a particular locale.
*
* @param locale the locale
*/
public ResourceGroup( final Locale locale )
{
m_locale = locale;
}
public Locale getLocale()
{
return m_locale;
}
public String format( final String base, final String key, final Object[] args )
{
final String pattern = getPattern( base, key );
final MessageFormat messageFormat = new MessageFormat( pattern );
messageFormat.setLocale( m_locale );
return messageFormat.format( args );
}
public ResourceBundle getBundle( final String base )
throws MissingResourceException
{
ResourceBundle result = (ResourceBundle) m_bundles.get( base );
if( null != result ) return result;
// bundle wasn't cached, so load it, cache it, and return it.
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
result = ResourceBundle.getBundle( base, m_locale, classLoader );
m_bundles.put( base, result );
return result;
}
public String getPattern( final String base, final String key )
throws MissingResourceException
{
final ResourceBundle bundle = getBundle( base );
final Object object = bundle.getObject( key );
// is the resource a single string
if( object instanceof String )
{
return (String)object;
}
else if( object instanceof String[] )
{
//if string array then randomly pick one
final String[] strings = (String[])object;
return strings[ RANDOM.nextInt( strings.length ) ];
}
else
{
throw new MissingResourceException( "Unable to find resource of appropriate type.",
"java.lang.String",
key );
}
}
}
1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/aut/i18n/XMLResourceBundle.java
Index: XMLResourceBundle.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.aut.i18n;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.Hashtable;
import java.util.Locale;
import java.util.MissingResourceException;
import org.apache.xalan.xpath.XObject;
import org.apache.xalan.xpath.XPath;
import org.apache.xalan.xpath.XPathProcessorImpl;
import org.apache.xalan.xpath.XPathSupport;
import org.apache.xalan.xpath.xml.PrefixResolverDefault;
import org.apache.xalan.xpath.xml.XMLParserLiaisonDefault;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xerces.dom.TextImpl;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* @author <a href="mailto:mengelhart@earthtrip.com">Mike Engelhart</a>
* @author <a href="mailto:neeme@one.lv">Neeme Praks</a>
* @author <a href="mailto:oleg@one.lv">Oleg Podolsky</a>
* @version $Id: XMLResourceBundle.java,v 1.1 2001/02/26 00:39:43 donaldp Exp $
*/
public class XMLResourceBundle {
// Cache for storing string values for existing XPaths
private Hashtable cacheIS = new Hashtable();
// Cache for storing non-existing XPaths
private Hashtable cacheNO = new Hashtable();
private Document resource;
public String bundleName = ""; //used by getLocale()
protected XMLResourceBundle parent = null;
public XMLResourceBundle( Document doc, String name, XMLResourceBundle p ) {
System.out.print( "Constructing XMLResourceBundle: " + name );
if ( p != null )
System.out.println( " --> parent: " + p.bundleName );
else
System.out.println( " --> parent: " + p );
this.resource = doc;
this.bundleName = name;
this.parent = p;
}
public void addToCache( String key, String value ) {
cacheIS.put( key, value );
}
public Document getResource() {
return this.resource;
}
// gets string without throwing an exception, returns empty string instead
public String getStringSimple( String xPathKey ) {
String result = "";
try {
result = getString( xPathKey );
} catch ( MissingResourceException e ) {
// do nothing
}
return result;
}
public String getString( String xPathKey ) throws MissingResourceException {
if ( cacheIS.containsKey( xPathKey ) )
return ( String ) cacheIS.get( xPathKey );
if ( cacheNO.containsKey( xPathKey ) )
new MissingResourceException( "Unable to locate resource: " + xPathKey, "XMLResourceBundle", xPathKey );
Node root = this.resource.getDocumentElement();
try {
Node node = XPathAPI.selectSingleNode( root, xPathKey );
if ( node != null ) {
String temp = getTextNodeAsString( node );
addToCache( xPathKey, temp );
return temp;
} else {
if ( this.parent != null )
return this.parent.getString( xPathKey );
else
throw new Exception();
}
} catch ( Exception e ) {
// no nodes returned??
cacheNO.put( xPathKey, "" );
throw new MissingResourceException( "Unable to locate resource: " + xPathKey, "XMLResourceBundle", xPathKey );
}
}
public String getString( Node role, String key ) throws MissingResourceException {
try {
Node node = XPathAPI.selectSingleNode( role, key );
if ( node != null )
return getTextNodeAsString( node );
else
throw new Exception();
} catch ( Exception e ) {
// no nodes returned??
throw new MissingResourceException( "Unable to locate resource: " + key, "XMLResourceBundle", key );
}
}
private String getTextNodeAsString( Node node ) throws MissingResourceException {
node = node.getFirstChild();
if ( node.getNodeType() == Node.TEXT_NODE )
return ( ( TextImpl ) node ).getData();
else
throw new MissingResourceException( "Unable to locate XMLResourceBundle", "XMLResourceBundleFactory", "" );
}
public Node getRole( String xPath ) {
Node root = resource.getDocumentElement();
try {
Node node = XPathAPI.selectSingleNode( root, xPath );
if ( node != null )
return node;
else
throw new Exception();
} catch ( Exception e ) {
// no nodes returned??
throw new MissingResourceException( "Unable to locate resource: " + xPath, "XMLResourceBundle", xPath );
}
}
public Node getRole( Node role, String xPath ) {
try {
Node node = XPathAPI.selectSingleNode( role, xPath );
if ( node != null )
return node;
else
throw new Exception();
} catch ( Exception e ) {
// no nodes returned??
throw new MissingResourceException( "Unable to locate resource: " + xPath, "XMLResourceBundle", xPath );
}
}
public XPath createXPath( String str, Node namespaceNode ) throws SAXException {
XPathSupport xpathSupport = new XMLParserLiaisonDefault();
if ( null == namespaceNode )
throw new SAXException( "A namespace node is required to resolve prefixes!" );
PrefixResolverDefault prefixResolver = new PrefixResolverDefault( ( namespaceNode.getNodeType() == Node.DOCUMENT_NODE ) ? ( ( Document ) namespaceNode ).getDocumentElement() : namespaceNode );
// Create the XPath object.
XPath xpath = new XPath();
// Create a XPath parser.
XPathProcessorImpl parser = new XPathProcessorImpl( xpathSupport );
parser.initXPath( xpath, str, prefixResolver );
return xpath;
}
public Locale getLocale() {
String bundle = bundleName.substring( 0, bundleName.indexOf( ".xml" ) );
int localeStart = bundle.indexOf( "_" );
if ( localeStart == -1 )
return new Locale( "", "", "" );
bundle = bundle.substring( localeStart + 1 );
localeStart = bundle.indexOf( "_" );
if ( localeStart == -1 )
return new Locale( bundle, "", "" );
String lang = bundle.substring( 0, localeStart );
bundle = bundle.substring( localeStart + 1 );
localeStart = bundle.indexOf( "_" );
if ( localeStart == -1 )
return new Locale( lang, bundle, "" );
String country = bundle.substring( 0, localeStart );
bundle = bundle.substring( localeStart + 1 );
return new Locale( lang, country, bundle );
}
}
1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/aut/i18n/XMLResourceBundleFactory.java
Index: XMLResourceBundleFactory.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.aut.i18n;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Vector;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xerces.dom.TextImpl;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* @author <a href="mailto:mengelhart@earthtrip.com">Mike Engelhart</a>
* @author <a href="mailto:neeme@one.lv">Neeme Praks</a>
* @author <a href="mailto:oleg@one.lv">Oleg Podolsky</a>
* @version $Id: XMLResourceBundleFactory.java,v 1.1 2001/02/26 00:39:43 donaldp Exp $
*/
public class XMLResourceBundleFactory {
protected static Hashtable cache = new Hashtable();
protected static String directory;
protected XMLResourceBundleFactory() {}
public static XMLResourceBundle getBundle( String name ) throws MissingResourceException {
return getBundle( name, Locale.getDefault() );
}
public static XMLResourceBundle getBundle( String name, Locale loc ) throws MissingResourceException {
return getBundle( name, loc, false );
}
public static XMLResourceBundle getBundle( String name, Locale loc, boolean cacheAtStartup ) throws MissingResourceException {
XMLResourceBundle parent = null;
String bundleName = getBundleName( name, loc );
// first look in the cache - if there grab it
XMLResourceBundle bundle = getCachedBundle( bundleName );
if ( bundle != null )
return bundle;
// if bundle is not in cache try loading the bundle using the given name and locale bundleName
Document doc = null;
doc = loadResourceBundle( bundleName );
if ( doc != null ) {
if ( ! loc.getLanguage().equals( "" ) )
parent = getParentBundle( name, loc, cacheAtStartup );
bundle = new XMLResourceBundle( doc, bundleName, parent );
if ( cacheAtStartup )
storeTextElements( bundle, bundle.getResource(), "" );
updateCache( bundleName, bundle );
return bundle;
}
// if the locale's language is "" then we've already tried to load the default resource and it's not available
while ( ! loc.getLanguage().equals( "" ) ) {
// if the given bundle name is not found, then try loading using a shortened Locale
loc = getParentLocale( loc );
bundleName = getBundleName( name, loc );
// first look in the cache - if there grab it and return
bundle = getCachedBundle( bundleName );
if ( bundle != null )
return bundle;
// try loading the bundle using the given name and locale bundleName
doc = loadResourceBundle( bundleName );
if ( doc != null ) {
if ( ! loc.getLanguage().equals( "" ) )
parent = getParentBundle( name, loc, cacheAtStartup );
bundle = new XMLResourceBundle( doc, bundleName, parent );
if ( cacheAtStartup )
storeTextElements( bundle, bundle.getResource(), "" );
updateCache( bundleName, bundle );
return bundle;
}
}
throw new MissingResourceException( "Unable to locate resource: " + bundleName, "XMLResourceBundleFactory", "" );
}
protected synchronized static XMLResourceBundle getParentBundle( String name, Locale loc ) {
return getParentBundle( name, loc, false );
}
protected synchronized static XMLResourceBundle getParentBundle( String name, Locale loc, boolean cacheAtStartup ) {
loc = getParentLocale( loc );
String bundleName = getBundleName( name, loc );
Document doc = loadResourceBundle( bundleName );
XMLResourceBundle bundle = null;
if ( doc != null ) {
if ( ! loc.getLanguage().equals( "" ) )
bundle = getParentBundle( name, loc );
bundle = new XMLResourceBundle( doc, bundleName, bundle );
if ( cacheAtStartup )
storeTextElements( bundle, bundle.getResource(), "" );
updateCache( bundleName, bundle );
}
return bundle;
}
// this method returns the next locale up the parent hierarchy
// e.g.; the parent of new Locale("en","us","mac")
// would be new Locale("en", "us", "");
protected static Locale getParentLocale( Locale loc ) {
if ( loc.getVariant().equals( "" ) ) {
if ( loc.getCountry().equals( "" ) )
loc = new Locale( "", "", "" );
else
loc = new Locale( loc.getLanguage(), "", "" );
} else
loc = new Locale( loc.getLanguage(), loc.getCountry(), "" );
return loc;
}
protected synchronized static XMLResourceBundle getCachedBundle( String bundleName ) {
/*
SoftReference ref = (SoftReference)(cache.get(bundleName));
if (ref != null)
return (XMLResourceBundle) ref.get();
else
return null;
*/
return ( XMLResourceBundle ) ( cache.get( bundleName ) );
}
protected synchronized static void updateCache( String bundleName, XMLResourceBundle bundle ) {
cache.put( bundleName, bundle );
}
/* protected static String getBundleName(String name, Locale loc)
{
StringBuffer sb = new StringBuffer(name);
if (! loc.getLanguage().equals(""))
{
sb.append("_");
sb.append(loc.getLanguage());
}
if (! loc.getCountry().equals(""))
{
sb.append("_");
sb.append(loc.getCountry());
}
if (! loc.getVariant().equals(""))
{
sb.append("_");
sb.append(loc.getVariant());
}
// should all the files have an extension of .xml? Seems reasonable
sb.append(".xml");
return sb.toString();
}
*/
protected static String getBundleName( String name, Locale loc ) {
String lang = loc.getLanguage();
StringBuffer sb = new StringBuffer( getDirectory() );
if ( lang.length() > 0 ) sb.append( "/" ).append( lang );
sb.append( "/" ).append( name ).append( ".xml" );
return sb.toString();
}
public static XMLResourceBundle getBundle( String fileName, String localeName ) throws MissingResourceException {
return getBundle( fileName, new Locale( localeName, localeName ) );
}
public static XMLResourceBundle getBundleFromFilename( String bundleName ) throws MissingResourceException {
return getBundleFromFilename( bundleName, true );
}
public static XMLResourceBundle getBundleFromFilename( String bundleName, boolean cacheAtStartup ) throws MissingResourceException {
Document doc = null;
doc = loadResourceBundle( getDirectory() + "/" + bundleName );
XMLResourceBundle bundle = getCachedBundle( bundleName );
if ( bundle != null )
return bundle;
if ( doc != null ) {
bundle = new XMLResourceBundle( doc, bundleName, null );
if ( cacheAtStartup )
storeTextElements( bundle, bundle.getResource(), "" );
updateCache( bundleName, bundle );
return bundle;
}
throw new MissingResourceException( "Unable to locate resource: " + bundleName, "XMLResourceBundleFactory", "" );
}
// Load the XML document based on bundleName
protected static Document loadResourceBundle( String bundleName ) {
try {
DOMParser parser = new DOMParser();
parser.parse( bundleName );
return parser.getDocument();
} catch ( IOException e ) {
return null;
}
catch ( SAXException e ) {
return null;
}
}
public static void setDirectory( String dir ) {
directory = dir;
}
public static String getDirectory() {
return ( directory != null ? directory : "" );
}
// Steps through the bundle tree and stores all text element values
// in bundle's cache, and also stores attributes for all element nodes.
// Parent must be am element-type node.
private static void storeTextElements( XMLResourceBundle bundle, Node parent, String pathToParent ) {
NodeList children = parent.getChildNodes();
int childnum = children.getLength();
for ( int i = 0; i < childnum; i++ ) {
Node child = children.item( i );
if ( child.getNodeType() == Node.ELEMENT_NODE ) {
String pathToChild = pathToParent + '/' + child.getNodeName();
NamedNodeMap attrs = child.getAttributes();
if ( attrs != null ) {
Node temp = null;
String pathToAttr = null;
int attrnum = attrs.getLength();
for ( int j = 0; j < attrnum; j++ ) {
temp = attrs.item( j );
pathToAttr = "/@" + temp.getNodeName();
bundle.addToCache( pathToChild + pathToAttr, temp.getNodeValue() );
}
}
String childValue = getTextValue( child );
if ( childValue != null )
bundle.addToCache( pathToChild, childValue );
else
storeTextElements( bundle, child, pathToChild );
}
}
}
private static String getTextValue( Node element ) {
NodeList list = element.getChildNodes();
int listsize = list.getLength();
Node item = null;
String itemValue = null;
for ( int i = 0; i < listsize; i++ ) {
item = list.item( i );
if ( item.getNodeType() != Node.TEXT_NODE ) return null;
itemValue = item.getNodeValue(); if ( itemValue == null ) return null;
itemValue = itemValue.trim(); if ( itemValue.length() == 0 ) return null;
return itemValue;
}
return null;
}
}
1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/aut/i18n/XPathAPI.java
Index: XPathAPI.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.aut.i18n;
import org.apache.xalan.xpath.XObject;
import org.apache.xalan.xpath.XPath;
import org.apache.xalan.xpath.XPathProcessorImpl;
import org.apache.xalan.xpath.XPathSupport;
import org.apache.xalan.xpath.xml.PrefixResolverDefault;
import org.apache.xalan.xpath.xml.XMLParserLiaisonDefault;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* The methods in this class are convenience methods into the
* low-level XPath API. We would like to eventually move these
* methods into the XPath core, but would like to do some peer
* review first to make sure we have it right.
* Please note that these methods execute pure XPaths. They do not
* implement those parts of XPath extended by XSLT, such as the
* document() function). If you want to install XSLT functions, you
* have to use the low-level API.
* These functions tend to be a little slow, since a number of objects must be
* created for each evaluation. A faster way is to precompile the
* XPaths using the low-level API, and then just use the XPaths
* over and over.
*
* @author <a href="mailto:mengelhart@earthtrip.com">Mike Engelhart</a>
* @see http://www.w3.org/TR/xpath
* @version $Id: XPathAPI.java,v 1.1 2001/02/26 00:39:43 donaldp Exp $
*/
public class XPathAPI {
/**
* Use an XPath string to select a single node. XPath namespace
* prefixes are resolved from the context node, which may not
* be what you want (see the next method).
*
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @return The first node found that matches the XPath, or null.
*/
public static Node selectSingleNode( Node contextNode, String str )
throws SAXException {
return selectSingleNode( contextNode, str, contextNode );
}
/**
* Use an XPath string to select a single node.
* XPath namespace prefixes are resolved from the namespaceNode.
*
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
* @return The first node found that matches the XPath, or null.
*/
public static Node selectSingleNode( Node contextNode, String str, Node namespaceNode )
throws SAXException {
// Have the XObject return its result as a NodeSet.
NodeList nl = selectNodeList( contextNode, str, namespaceNode );
// Return the first node, or null
return ( nl.getLength() > 0 ) ? nl.item( 0 ) : null;
}
/**
* Use an XPath string to select a nodelist.
* XPath namespace prefixes are resolved from the contextNode.
*
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @return A nodelist, should never be null.
*/
public static NodeList selectNodeList( Node contextNode, String str )
throws SAXException {
return selectNodeList( contextNode, str, contextNode );
}
/**
* Use an XPath string to select a nodelist.
* XPath namespace prefixes are resolved from the namespaceNode.
*
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
* @return A nodelist, should never be null.
*/
public static NodeList selectNodeList( Node contextNode, String str, Node namespaceNode )
throws SAXException {
// Execute the XPath, and have it return the result
XObject list = eval( contextNode, str, namespaceNode );
// Have the XObject return its result as a NodeSet.
return list.nodeset();
}
/**
* Evaluate XPath string to an XObject. Using this method,
* XPath namespace prefixes will be resolved from the namespaceNode.
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
* @see org.apache.xalan.xpath.XObject
* @see org.apache.xalan.xpath.XNull
* @see org.apache.xalan.xpath.XBoolean
* @see org.apache.xalan.xpath.XNumber
* @see org.apache.xalan.xpath.XString
* @see org.apache.xalan.xpath.XRTreeFrag
*/
public static XObject eval( Node contextNode, String str )
throws SAXException {
return eval( contextNode, str, contextNode );
}
/**
* Evaluate XPath string to an XObject.
* XPath namespace prefixes are resolved from the namespaceNode.
* The implementation of this is a little slow, since it creates
* a number of objects each time it is called. This could be optimized
* to keep the same objects around, but then thread-safety issues would arise.
*
* @param contextNode The node to start searching from.
* @param str A valid XPath string.
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
* @see org.apache.xalan.xpath.XObject
* @see org.apache.xalan.xpath.XNull
* @see org.apache.xalan.xpath.XBoolean
* @see org.apache.xalan.xpath.XNumber
* @see org.apache.xalan.xpath.XString
* @see org.apache.xalan.xpath.XRTreeFrag */
public static XObject eval( Node contextNode, String str, Node namespaceNode )
throws SAXException {
// Since we don't have a XML Parser involved here, install some default support
// for things like namespaces, etc.
// (Changed from: XPathSupportDefault xpathSupport = new XPathSupportDefault();
// because XPathSupportDefault is weak in a number of areas... perhaps
// XPathSupportDefault should be done away with.)
XPathSupport xpathSupport = new XMLParserLiaisonDefault();
if ( null == namespaceNode )
namespaceNode = contextNode;
// Create an object to resolve namespace prefixes.
// XPath namespaces are resolved from the input context node's document element
// if it is a root node, or else the current context node (for lack of a better
// resolution space, given the simplicity of this sample code).
PrefixResolverDefault prefixResolver = new PrefixResolverDefault( ( namespaceNode.getNodeType() == Node.DOCUMENT_NODE )
? ( ( Document ) namespaceNode ).getDocumentElement() :
namespaceNode );
// Create the XPath object.
XPath xpath = new XPath();
// Create a XPath parser.
XPathProcessorImpl parser = new XPathProcessorImpl( xpathSupport );
parser.initXPath( xpath, str, prefixResolver );
// Execute the XPath, and have it return the result
return xpath.execute( xpathSupport, contextNode, prefixResolver );
}
}